package com.erp.erp_ui.business.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.erp.enums.*;
import com.erp.erp_entitys.Customer.CustomerInformationRecordReq;
import com.erp.erp_entitys.Customer.CustomerInformationRecordRes;
import com.erp.erp_entitys.User.UserEntity;
import com.erp.erp_entitys.business.entity.*;
import com.erp.erp_entitys.business.req.*;
import com.erp.erp_entitys.business.rsp.*;
import com.erp.erp_entitys.log.entity.DataInfoLogEntity;
import com.erp.erp_entitys.money.entity.ReceivePaymentDetailEntity;
import com.erp.erp_entitys.money.entity.ReceivePaymentEntity;
import com.erp.erp_entitys.warehouse.entity.AnnexEntity;
import com.erp.erp_entitys.warehouse.entity.StockEntity;
import com.erp.erp_entitys.warehouse.entity.TempAnnexEntity;
import com.erp.erp_entitys.warehouse.req.StockReq;
import com.erp.erp_entitys.warehouse.rsp.CustomerInfoRsp;
import com.erp.erp_entitys.warehouse.rsp.ProductInfoRsp;
import com.erp.erp_servers.ShipmentPlan.IShipmentPlanService;
import com.erp.erp_servers.User.IUserService;
import com.erp.erp_servers.business.*;
import com.erp.erp_servers.log.IDataInfoLogService;
import com.erp.erp_servers.money.IReceivePaymentDetailService;
import com.erp.erp_servers.money.IReceivePaymentService;
import com.erp.erp_servers.warehouse.*;
import com.erp.erp_ui.business.req.*;
import com.erp.erp_ui.business.vo.*;
import com.erp.erp_ui.money.req.OperationReq;
import com.erp.erp_ui.warehouse.enums.DataIsValidEnum;
import com.erp.erp_ui.warehouse.req.AnnexReq;
import com.erp.erp_ui.warehouse.vo.AnnexVo;
import com.erp.utils.*;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName : ExportContractService
 * @Description : 出口业务-外销业务逻辑层
 * @Author : lst
 * @Date: 2021-01-17 11:14
 */
@Service
public class ExportContractService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ExportContractService.class);

    /**
     * 外销主表接口
     */
    private final IExportContractService exportContractService;

    /**
     * 外销产品接口
     */
    private final IExportContractProductService exportContractProductService;

    /**
     * 外销产品配件接口
     */
    private final IExportContractProductPartsService exportContractProductPartsService;

    /**
     * 外销费用接口
     */
    private final IExportContractCostService exportContractCostService;

    /**
     * 附件接口
     */
    private final IAnnexService annexService;

    /**
     * 临时附件接口
     */
    private final ITempAnnexService tempAnnexService;

    /**
     * 库存接口
     */
    private final IStockService stockService;

    /**
     * 报价接口
     */
    private final IOfferService offerService;

    /**
     * 报价明细接口
     */
    private final IOfferDetailService offerDetailService;

    /**
     * 报价配件接口
     */
    private final IOfferProductPartsService offerProductPartsService;

    /**
     * 报价费用接口
     */
    private final IOfferCostService offerCostService;

    /**
     * 出运计划接口
     */
    private final IShipmentPlanService shipmentPlanService;

    /**
     * 资金管理-收款主表接口
     */
    private final IReceivePaymentService receivePaymentService;

    /**
     * 资金管理-收款明细接口
     */
    private final IReceivePaymentDetailService receivePaymentDetailService;

    /**
     * 出运明细接口
     */
    private final ICarryDetailService carryDetailService;

    /**
     * 操作日志信息接口
     */
    private final IDataInfoLogService dataInfoLogService;

    /**
     * 调拨明细接口
     */
    private final ITransferDetailService transferDetailService;

    /**
     * 其它出库接口
     */
    private final IOtherOutStockService otherOutStockService;

    /**
     * 用户接口
     */
    private final IUserService userService;

    @Autowired
    public ExportContractService(IExportContractService exportContractService,
                                 IExportContractProductService exportContractProductService,
                                 IExportContractProductPartsService exportContractProductPartsService,
                                 IExportContractCostService exportContractCostService,
                                 IAnnexService annexService,
                                 ITempAnnexService tempAnnexService,
                                 IStockService stockService,
                                 IOfferService offerService,
                                 IOfferDetailService offerDetailService,
                                 IOfferProductPartsService offerProductPartsService,
                                 IOfferCostService offerCostService,
                                 IShipmentPlanService shipmentPlanService,
                                 IReceivePaymentService receivePaymentService,
                                 IReceivePaymentDetailService receivePaymentDetailService,
                                 ICarryDetailService carryDetailService,
                                 IDataInfoLogService dataInfoLogService,
                                 ITransferDetailService transferDetailService,
                                 IOtherOutStockService otherOutStockService,
                                 IUserService userService) {
        this.exportContractService = exportContractService;
        this.exportContractProductService = exportContractProductService;
        this.exportContractProductPartsService = exportContractProductPartsService;
        this.exportContractCostService = exportContractCostService;
        this.annexService = annexService;
        this.tempAnnexService = tempAnnexService;
        this.stockService = stockService;
        this.offerService = offerService;
        this.offerDetailService = offerDetailService;
        this.offerProductPartsService = offerProductPartsService;
        this.offerCostService = offerCostService;
        this.shipmentPlanService = shipmentPlanService;
        this.receivePaymentService = receivePaymentService;
        this.receivePaymentDetailService = receivePaymentDetailService;
        this.carryDetailService = carryDetailService;
        this.dataInfoLogService = dataInfoLogService;
        this.transferDetailService = transferDetailService;
        this.otherOutStockService = otherOutStockService;
        this.userService = userService;
    }

    /**
     * 导入报价
     * @param req 查询参数
     * @return 报价信息
     */
    public PageInfo<ImportOfferVo> getImportOffer(ImportOfferReq req){
        //初始化查询对象
        ImportOfferInfoReq infoReq = new ImportOfferInfoReq();
        //赋值
        BeanUtils.copyProperties(req, infoReq);
        if(StringUtils.isNotEmpty(req.getBillNo())){
            //去掉前后空格
            infoReq.setBillNo(req.getBillNo().trim());
        }
        //调用接口查询报价信息
        List<OfferEntity> offerList = offerService.getImportOfferListInfo(infoReq);
        List<ImportOfferVo> offerVos = new ArrayList<>();
        PageInfo pageInfo = new PageInfo(offerList);
        if(CollectionUtils.isEmpty(offerList)){
            pageInfo.setList(offerVos);
            return pageInfo;
        }
        for(OfferEntity offer : offerList){
            ImportOfferVo vo = new ImportOfferVo();
            //赋值
            BeanUtils.copyProperties(offer, vo);
            //报价时间
            vo.setTime(DateUtils.format(offer.getTime(), DateUtils.DATE_PATTERN));
            //创建时间
            vo.setCreateDate(DateUtils.format(offer.getCreateDate(), DateUtils.DATE_PATTERN));

            offerVos.add(vo);
        }
        pageInfo.setList(offerVos);
        return pageInfo;
    }


    /**
     * 通过报价id获取报价明细及对应配件信息
     * @param id 报价id
     * @return 获取报价明细及对应配件信息
     */
    public List<OfferProductDetailVo> getImportOfferDetail(Integer id){
        //初始化回参对象集合
        List<OfferProductDetailVo> detailList = new ArrayList<>();
        if(null == id){
            return detailList;
        }
        //1.获取报价主表信息
        OfferEntity offer = offerService.queryById(id);
        //初始化报价回参实体
        OfferInfoVo offerInfoVo = new OfferInfoVo();
        //赋值
        BeanUtils.copyProperties(offer, offerInfoVo);
        //判断客户是否为合作客户
        CustomerInfoRsp customer = otherOutStockService.getCustomerByCode(offer.getCustomerCode());
        //合作客户(type = 0 或 type = 1)
        boolean partner = customer.getType().equals("0") || customer.getType().equals("1");
        offerInfoVo.setPartner(partner);

        //2.获取报价费用数据
        OfferCostEntity costReq = new OfferCostEntity();
        //设置报价id
        costReq.setParentId(id);
        //获取有效数据
        costReq.setValid(DataIsValidEnum.VALID.getId());
        //查询结果
        List<OfferCostEntity> costEntities = offerCostService.queryAll(costReq);
        //费用集合
        List<OfferCostDetailVo> costList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(costEntities)){
            for(OfferCostEntity cost : costEntities){
                OfferCostDetailVo costVo = new OfferCostDetailVo();
                //赋值
                BeanUtils.copyProperties(cost, costVo);

                costList.add(costVo);
            }
        }

        //3.获取对应附件信息
        AnnexEntity annex = new AnnexEntity();
        //设置模块id
        annex.setModuleId(ModuleTypeEnum.BUSINESS_OFFER.getId());
        //设置父id
        annex.setParentId(id);
        //设置数据有效
        annex.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询附件信息
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        //附件集合
        List<AnnexVo> annexVos = annexList.stream().map(p -> {
            AnnexVo annexVo = new AnnexVo();
            //赋值
            BeanUtils.copyProperties(p, annexVo);
            //上传时间转换
            annexVo.setUploadTime(DateUtils.format(p.getUploadTime(), DateUtils.DATE_TIME_PATTERN));

            return annexVo;
        }).collect(Collectors.toList());

        //4.获取产品信息
        OfferDetailEntity offerDetailReq = new OfferDetailEntity();
        //报价id
        offerDetailReq.setParentId(id);
        //有效数据
        offerDetailReq.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询报价产品明细数据
        List<OfferDetailEntity> offerDetailList = offerDetailService.queryAll(offerDetailReq);
        if(!CollectionUtils.isEmpty(offerDetailList)){
            for(OfferDetailEntity detailEntity : offerDetailList){
                //初始化回参对象
                OfferProductDetailVo productDetailVo = new OfferProductDetailVo();
                //赋值
                BeanUtils.copyProperties(detailEntity, productDetailVo);
                //设置报价相关信息
                productDetailVo.setOfferInfo(offerInfoVo);
                //设置报价费用数据
                productDetailVo.setCostList(costList);
                //设置报价附件
                productDetailVo.setAnnexList(annexVos);
                //获取已被下游调用数量
                RemainingQuantityInfoReq infoReq = new RemainingQuantityInfoReq();
                //报价单号
                infoReq.setBillNo(offer.getBillNo());
                //产品编码
                infoReq.setProductCode(detailEntity.getProductCode());
                //规格编码
                infoReq.setSpecificationCode(detailEntity.getSpecificationCode());
                //已被调用数量
                BigDecimal sum = getRemainingQuantity(infoReq);
                //剩余数量=库存数量-被调用数量
                BigDecimal productNum = new BigDecimal("0");
                if(StringUtil.isNotEmpty(detailEntity.getProductNum())){
                    productNum = detailEntity.getProductNum();
                }
                BigDecimal remainingQuantity = productNum.subtract(sum);
                if(remainingQuantity.compareTo(BigDecimal.ZERO) < 1){
                    //剩余数量小于等于零，该产品无法再被调用
                    continue;
                }
                //设置剩余数量
                productDetailVo.setRemainingQuantity(remainingQuantity);
                //报价单号
                productDetailVo.setOfferBillNo(offer.getBillNo());
                //获取对应配件信息
                OfferProductPartsEntity partsReq = new OfferProductPartsEntity();
                //设置报价id
                partsReq.setParentId(id);
                //设置产品明细id
                partsReq.setProductDetailId(detailEntity.getId());
                //设置数据有效性
                partsReq.setValid(DataIsValidEnum.VALID.getId());
                //查询结果
                List<OfferProductPartsEntity> partsEntityList = offerProductPartsService.queryAll(partsReq);
                if(!CollectionUtils.isEmpty(partsEntityList)){
                    List<OfferProductPartsDetailVo> partsList = partsEntityList.stream().map(p ->{
                        OfferProductPartsDetailVo partsVo = new OfferProductPartsDetailVo();
                        //赋值
                        BeanUtils.copyProperties(p, partsVo);
                        return partsVo;
                    }).collect(Collectors.toList());

                    //添加相关配件集合
                    productDetailVo.setPartsList(partsList);
                }

                detailList.add(productDetailVo);
            }
        }
        return detailList;
    }

    /**
     * 新增、修改
     * @param req 新增、修改入参
     * @param creator 创建人
     * @param createNo 创建人编码
     * @return 新增、修改结果
     */
    @Transactional(rollbackFor = Exception.class)
    public R add(AddExportContractReq req, String creator, String createNo) throws ParseException {
        if(!StringUtils.isEmpty(req.getBillNo())){
            //单号去除前后空格
            String newBillNo = req.getBillNo().trim();
            req.setBillNo(newBillNo);
        }
        //一：数据校验
        //1.单号唯一性校验
        boolean billNoCheckFlag = (null != req.getId() && req.getBillNo().equals(req.getNewBillNo()));
        if(!billNoCheckFlag){
            //单号做唯一校验
            boolean billNoFlag = checkRepeatBillNo(req.getBillNo());
            if(!billNoFlag){
                return R.buildError(ResultStatusEnum.BILL_NO_REPEAT);
            }
        }
        //2.信用额度校验
        /*if(1 == req.getRechargeOccupancy()){
            boolean flag = checkCreditQuota(req);
            if(!flag){
                return R.buildError(ResultStatusEnum.CHECK_CREDIT_QUOTA_ERROR);
            }
        }*/

        //二：主表新增
        Integer id = insert(req, creator, createNo);
        if(id == null){
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }

        //三：明细新增及对应配件
        insertDetail(req, id, creator, createNo);

        //四：费用新增
        addCost(req, id, creator, createNo);

        //五：添加附件信息
        boolean flag = addAnnex(req, id, creator, createNo);
        if(!flag){
            LOGGER.info("出口业务-外销-批量新增附件异常");
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        //删除临时附件信息
        deleteTempAnnex(req.getAnnexList());
        return R.build(ResultStatusEnum.SUCCESS);
    }

    /**
     * 合同总额不能超过剩余信用额度
     * @param req 入参实体
     * @return 信用额度校验是否通过(true:通过 false:不通过)
     */
    private boolean checkCreditQuota(AddExportContractReq req){
        //获取客户编码
        String customerCode = req.getCustomerCode();
        //根据客户编码获取该客户已使用信用额度
        BigDecimal sumTotalContractAmount = exportContractService.getSumTotalContractAmount(customerCode);
        //根据客户编码获取该客户收汇金额合计
        BigDecimal sumCollectionAmount = receivePaymentService.getSumCollectionAmount(customerCode);
        //该客户已使用信用额度
        BigDecimal usdCreditQuota = sumTotalContractAmount.subtract(sumCollectionAmount);
        //该客户总信用额度
        BigDecimal creditQuota = new BigDecimal("0");
        if(StringUtil.isNotEmpty(req.getCreditQuota())){
            creditQuota = req.getCreditQuota();
        }
        //该客户剩余信用额度
        BigDecimal lastCreditQuota = creditQuota.subtract(usdCreditQuota);
        if(req.getTotalContractAmount().compareTo(lastCreditQuota) == 1){
            //合同总额不能超过剩余信用额度
            return false;
        }
        return true;
    }

    /**
     * 批量处理临时附件信息，将临时附件设置为失效
     * @param annexReqs
     */
    private void deleteTempAnnex(List<AnnexReq> annexReqs){
        //没有附件
        if(CollectionUtils.isEmpty(annexReqs)){
            return;
        }
        //存在附件
        for(AnnexReq annex : annexReqs){
            if(null != annex.getNews()){
                //旧附件,不用修改
                continue;
            }
            TempAnnexEntity tempAnnex = new TempAnnexEntity();
            //设置临时附件id
            tempAnnex.setId(annex.getId());
            //设置修改时间
            tempAnnex.setUpdateTime(new Date());
            //将附件设置为失效
            tempAnnex.setValid(DataIsValidEnum.INVALID.getId());
            tempAnnexService.update(tempAnnex);
        }

    }

    /**
     * 附件新增
     * @param req 入参信息
     * @param id 主表id
     * @param operator 操作人
     * @param operatorNo 操作人编码
     * @return 是否新增成功(true:成功 false:失败 )
     */
    private boolean addAnnex(AddExportContractReq req, Integer id, String operator, String operatorNo) {
        try {
            List<AnnexReq> annexReqs = req.getAnnexList();
            //没有附件,将该id关联的所有附件设为无效
            if(CollectionUtils.isEmpty(annexReqs)){
                AnnexEntity annexReq = new AnnexEntity();
                annexReq.setParentId(id);
                annexReq.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                List<AnnexEntity> annexList = annexService.queryAll(annexReq);
                if(!CollectionUtils.isEmpty(annexList)){
                    for(AnnexEntity annex : annexList){
                        AnnexEntity updateAnnex= new AnnexEntity();
                        updateAnnex.setId(annex.getId());
                        //将被删除的附件设为失效
                        updateAnnex.setValid(DataIsValidEnum.INVALID.getId());
                        annexService.update(updateAnnex);
                    }
                }
                return true;
            }
            //存在附件,新增附件信息
            List<AnnexEntity> list = new ArrayList<>();
            for(AnnexReq annexReq : annexReqs){
                if(null != annexReq.getNews()){
                    //属于旧附件 不新增
                    continue;
                }
                AnnexEntity annex = new AnnexEntity();
                BeanUtils.copyProperties(annexReq, annex);
                //设置关联模块id
                annex.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                //设置关联模块父id
                annex.setParentId(id);
                //设置上传时间
                annex.setUploadTime(DateUtils.convertStringToDate(annexReq.getUploadTime(), DateUtils.DATE_PATTERN));
                //设置修改时间
                annex.setUpdateTime(new Date());
                //设置操作人
                annex.setOperator(operator);
                //设置操作人编码
                annex.setOperatorNo(operatorNo);
                //设置数据有效
                annex.setValid(1);

                list.add(annex);
            }
            if(!CollectionUtils.isEmpty(list)){
                //附件批量新增
                annexService.batchInsert(list);
            }
            //获取删除的附件
            List<Integer> deleteAnnexIds = req.getDeleteAnnexIds();
            if(deleteAnnexIds.size() > 0){
                //存在被删除的旧附件，数据库删除
                for(Integer deleteAnnexId : deleteAnnexIds){
                    AnnexEntity annexEntity = new AnnexEntity();
                    //附件主键ID
                    annexEntity.setId(deleteAnnexId);
                    //将被删除的附件设为失效
                    annexEntity.setValid(DataIsValidEnum.INVALID.getId());
                    //删除时间
                    annexEntity.setUpdateTime(new Date());

                    annexService.update(annexEntity);
                }
            }
            return true;
        }catch (Exception e){
            throw new RuntimeException();
        }
    }

    /**
     * 费用新增
     * @param req 新增参数
     * @param id 主表id
     */
    private void addCost(AddExportContractReq req, Integer id, String creator, String createNo){
        if(CollectionUtils.isEmpty(req.getCostList())){
            return;
        }
        List<ExportContractCostEntity> addCostList = new ArrayList<>();
        //费用id
        List<Integer> newIds = new ArrayList<>();
        for(AddExportContractCostReq cost : req.getCostList()){
            ExportContractCostEntity updateReq = new ExportContractCostEntity();
            //赋值
            BeanUtils.copyProperties(cost, updateReq);

            if(null == cost.getId()){
                //新增

                //新增日志信息
                DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                //模块主表id
                dataInfoLog.setParentId(id);
                //模块id
                dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                //操作人编码
                dataInfoLog.setOperationCode(createNo);
                //操作人名称
                dataInfoLog.setOperationName(creator);
                //操作时间
                dataInfoLog.setOperationTime(new Date());
                //操作类型
                dataInfoLog.setOperationType(OperationTypeEnum.INSERT_DATA.getId());
                //操作内容
                dataInfoLog.setOperationContent("费用信息:");

                dataInfoLogService.insert(dataInfoLog);

                //父id
                updateReq.setParentId(id);
                //创建时间
                updateReq.setCreateDate(new Date());
                //设为有效
                updateReq.setValid(DataIsValidEnum.VALID.getId());

                addCostList.add(updateReq);
            }else {
                //修改

                ExportContractCostEntity costData = exportContractCostService.queryById(cost.getId());
                BeanChangeLogUtil logUtil = new BeanChangeLogUtil();
                String info = logUtil.contrastObj(costData, updateReq);
                if(StringUtils.isNotEmpty(info)){
                    //新增日志信息
                    DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                    //模块主表id
                    dataInfoLog.setParentId(id);
                    //模块id
                    dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                    //操作人编码
                    dataInfoLog.setOperationCode(createNo);
                    //操作人名称
                    dataInfoLog.setOperationName(creator);
                    //操作时间
                    dataInfoLog.setOperationTime(new Date());
                    //操作类型
                    //操作内容
                    dataInfoLog.setOperationContent("费用信息:" + info);
                    //操作类型
                    dataInfoLog.setOperationType(OperationTypeEnum.UPDATE_DATA.getId());

                    dataInfoLogService.insert(dataInfoLog);
                }

                //修改时间
                updateReq.setModifyTime(new Date());
                exportContractCostService.update(updateReq);
                newIds.add(updateReq.getId());
            }
        }
        //处理被删除的费用
        handleBeenDeletedCost(id, newIds);

        if(!CollectionUtils.isEmpty(addCostList)){
            //费用批量新增
            exportContractCostService.addList(addCostList);
        }
    }

    /**
     * 处理被删除的费用
     * @param id 报价id
     * @param newIds 费用id
     */
    private void handleBeenDeletedCost(int id, List<Integer> newIds){
        //修改-找出被删除的费用

        ExportContractCostEntity costReq = new ExportContractCostEntity();
        //设置报价id
        costReq.setParentId(id);
        //查询有效数据
        costReq.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询结果
        List<ExportContractCostEntity> costList = exportContractCostService.queryAll(costReq);
        if(!CollectionUtils.isEmpty(costList)){
            //获取id集合
            List<Integer> oldIds = costList.stream().map(p -> p.getId()).collect(Collectors.toList());
            //找出被删除的id
            Collection collection = new ArrayList(oldIds);
            collection.removeAll(newIds);
            if(collection.size() > 0){
                //遍历被删除的费用
                Iterator<Integer> ids = collection.iterator();
                while (ids.hasNext()){
                    int costId = ids.next();
                    ExportContractCostEntity updateReq = new ExportContractCostEntity();
                    //修改主键
                    updateReq.setId(costId);
                    //修改时间
                    updateReq.setModifyTime(new Date());
                    //设为无效
                    updateReq.setValid(DataIsValidEnum.INVALID.getId());

                    exportContractCostService.update(updateReq);
                }
            }
        }
    }

    /**
     * 明细新增
     * @param req 新增对象
     * @param id 主表id
     */
    public void insertDetail(AddExportContractReq req, int id, String creator, String createNo) throws ParseException {
        if(!CollectionUtils.isEmpty(req.getDetailList())){
            //获取明细id集合
            List<Integer> newIds = new ArrayList<>();
            for(AddExportContractProductReq detailReq : req.getDetailList()){
                //初始化明细对象
                ExportContractProductEntity detail = new ExportContractProductEntity();
                //赋值
                BeanUtils.copyProperties(detailReq, detail);
                //交货期日期转换
                detail.setDeliveryDate(DateUtils.convertStringToDate(detailReq.getDeliveryDate(), DateUtils.DATE_PATTERN));
                //设置主表id
                detail.setParentId(id);
                //设置数据有效性(0:无效 1:有效)
                detail.setValid(DataIsValidEnum.VALID.getId());
                if(null == detailReq.getId()){
                    if (req.getId() != null) {
                        //表明修改新增产品
                        //新增日志信息
                        DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                        //模块主表id
                        dataInfoLog.setParentId(id);
                        //模块id
                        dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                        //操作人编码
                        dataInfoLog.setOperationCode(createNo);
                        //操作人名称
                        dataInfoLog.setOperationName(creator);
                        //操作类型
                        dataInfoLog.setOperationType(OperationTypeEnum.INSERT_DATA.getId());
                        //操作时间
                        dataInfoLog.setOperationTime(new Date());
                        //操作内容
                        dataInfoLog.setOperationContent("产品信息:" + "产品编码:" + detail.getProductCode() + ",规格编码:" + detail.getSpecificationCode());

                        dataInfoLogService.insert(dataInfoLog);
                    }

                    //剩余数量默认等于入库数量
                    detail.setProductSurplusNum(detailReq.getProductNum());
                    //新增
                    exportContractProductService.insert(detail);
                    //获取明细id
                    Integer detailId = detail.getId();
                    newIds.add(detailId);
                    //配件新增
                    if(!CollectionUtils.isEmpty(detailReq.getPartsList())){
                        //初始化配件对象集合
                        List<ExportContractProductPartsEntity> partsList = new ArrayList<>();
                        for(AddExportContractProductPartsReq parts : detailReq.getPartsList()){
                            //初始化配件对象
                            ExportContractProductPartsEntity partsEntity = new ExportContractProductPartsEntity();
                            //赋值
                            BeanUtils.copyProperties(parts, partsEntity);
                            //报价id
                            partsEntity.setParentId(id);
                            //产品明细id
                            partsEntity.setDetailId(detailId);
                            //创建时间
                            partsEntity.setCreateDate(new Date());
                            //设置数据有效性(0:无效 1:有效)
                            partsEntity.setValid(DataIsValidEnum.VALID.getId());

                            partsList.add(partsEntity);
                        }
                        if(!CollectionUtils.isEmpty(partsList)){
                            //新增配件
                            exportContractProductPartsService.addList(partsList);
                        }

                    }
                }else {
                    //修改

                    //添加修改日志
                    //获取修改前对象数据
                    ExportContractProductEntity oldData = exportContractProductService.queryById(detailReq.getId());
                    BeanChangeLogUtil logUtil = new BeanChangeLogUtil();
                    String info = logUtil.contrastObj(oldData, detail);
                    if(StringUtils.isNotEmpty(info)){
                        //新增日志信息
                        DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                        //模块主表id
                        dataInfoLog.setParentId(id);
                        //模块id
                        dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                        //操作人编码
                        dataInfoLog.setOperationCode(createNo);
                        //操作人名称
                        dataInfoLog.setOperationName(creator);
                        //操作类型
                        dataInfoLog.setOperationType(OperationTypeEnum.UPDATE_DATA.getId());
                        //操作时间
                        dataInfoLog.setOperationTime(new Date());
                        //操作内容
                        dataInfoLog.setOperationContent("产品信息:" + info);

                        dataInfoLogService.insert(dataInfoLog);
                    }

                    //获取明细id
                    newIds.add(detailReq.getId());
                    //明细修改
                    exportContractProductService.update(detail);
                    //配件修改
                    if(!CollectionUtils.isEmpty(detailReq.getPartsList())){
                        List<Integer> newPartsIds = new ArrayList<>();
                        for(AddExportContractProductPartsReq parts : detailReq.getPartsList()){
                            if(null == parts.getId()){
                                //新增
                                //初始化配件对象
                                ExportContractProductPartsEntity partsEntity = new ExportContractProductPartsEntity();
                                //赋值
                                BeanUtils.copyProperties(parts, partsEntity);
                                //报价id
                                partsEntity.setParentId(id);
                                //产品明细id
                                partsEntity.setDetailId(detailReq.getId());
                                //创建时间
                                partsEntity.setCreateDate(new Date());
                                //设置数据有效性(0:无效 1:有效)
                                partsEntity.setValid(DataIsValidEnum.VALID.getId());

                                exportContractProductPartsService.insert(partsEntity);
                                //获取配件id
                                newPartsIds.add(partsEntity.getId());
                            }else {
                                //修改
                                if(detailReq.getId().equals(parts.getDetailId())){
                                    //获取配件id
                                    newPartsIds.add(parts.getId());
                                    //初始化配件对象
                                    ExportContractProductPartsEntity partsEntity = new ExportContractProductPartsEntity();
                                    //赋值
                                    BeanUtils.copyProperties(parts, partsEntity);
                                    //修改时间
                                    partsEntity.setModifyTime(new Date());

                                    exportContractProductPartsService.update(partsEntity);
                                }
                            }

                        }
                        //处理被删除的配件
                        handleBeenDeletedParts(detailReq.getId(), newPartsIds);
                    }
                }

            }

            //处理被删除的明细
            handleBeenDeletedDetail(req, id, newIds, creator, createNo);

        }
    }

    /**
     * 处理被删除的明细
     * @param req 明细
     * @param id 主表id
     * @param newIds 修改后未被删除的细id集合
     */
    private void handleBeenDeletedDetail(AddExportContractReq req, int id, List<Integer> newIds, String creator, String createNo){
        if(null != req.getId()){
            //修改-找出被删除的明细

            ExportContractProductEntity detailReq = new ExportContractProductEntity();
            //设置付款id
            detailReq.setParentId(id);
            //查询有效数据
            detailReq.setValid(DataIsValidEnum.VALID.getId());
            //调用接口查询结果
            List<ExportContractProductEntity> detailList = exportContractProductService.queryAll(detailReq);
            if(!CollectionUtils.isEmpty(detailList)){
                //获取id集合
                List<Integer> oldIds = detailList.stream().map(p -> p.getId()).collect(Collectors.toList());
                //找出被删除的id
                Collection collection = new ArrayList(oldIds);
                collection.removeAll(newIds);
                if(collection.size() > 0){
                    //遍历删除被删除的明细
                    Iterator<Integer> ids = collection.iterator();
                    while (ids.hasNext()){
                        int detailId = ids.next();

                        //添加日志
                        ExportContractProductEntity detailEntity = exportContractProductService.queryById(detailId);
                        //新增日志信息
                        DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                        //模块主表id
                        dataInfoLog.setParentId(id);
                        //模块id
                        dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                        //操作人编码
                        dataInfoLog.setOperationCode(createNo);
                        //操作人名称
                        dataInfoLog.setOperationName(creator);
                        //操作类型
                        dataInfoLog.setOperationType(OperationTypeEnum.DELETE_DATA.getId());
                        //操作时间
                        dataInfoLog.setOperationTime(new Date());
                        //操作内容
                        dataInfoLog.setOperationContent("产品信息:" + "产品编码:" + detailEntity.getProductCode() + ",规格编码:" + detailEntity.getSpecificationCode());

                        dataInfoLogService.insert(dataInfoLog);

                        ExportContractProductEntity detail = new ExportContractProductEntity();
                        detail.setId(detailId);
                        detail.setValid(DataIsValidEnum.INVALID.getId());
                        //将删除的明细设为无效
                        exportContractProductService.update(detail);

                        //获取对应的配件数据
                        ExportContractProductPartsEntity query = new ExportContractProductPartsEntity();
                        //报价id
                        query.setParentId(id);
                        //产品明细id
                        query.setDetailId(detailId);
                        //有效的数据
                        query.setValid(DataIsValidEnum.VALID.getId());
                        //调用接口查询
                        List<ExportContractProductPartsEntity> partsList = exportContractProductPartsService.queryAll(query);
                        if(!CollectionUtils.isEmpty(partsList)){
                            for(ExportContractProductPartsEntity partsEntity : partsList){
                                ExportContractProductPartsEntity updateReq = new ExportContractProductPartsEntity();
                                //修改主键
                                updateReq.setId(partsEntity.getId());
                                //修改时间
                                updateReq.setModifyTime(new Date());
                                //设为无效
                                updateReq.setValid(DataIsValidEnum.INVALID.getId());

                                exportContractProductPartsService.update(updateReq);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 处理被删除的配件
     * @param id 产品明细id
     * @param newIds 配件id
     */
    private void handleBeenDeletedParts(int id, List<Integer> newIds){
        //修改-找出被删除的明细

        ExportContractProductPartsEntity partsReq = new ExportContractProductPartsEntity();
        //设置产品明细id
        partsReq.setDetailId(id);
        //查询有效数据
        partsReq.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询结果
        List<ExportContractProductPartsEntity> partsList = exportContractProductPartsService.queryAll(partsReq);
        if(!CollectionUtils.isEmpty(partsList)){
            //获取id集合
            List<Integer> oldIds = partsList.stream().map(p -> p.getId()).collect(Collectors.toList());
            //找出被删除的id
            Collection collection = new ArrayList(oldIds);
            collection.removeAll(newIds);
            if(collection.size() > 0){
                //遍历删除被删除的明细
                Iterator<Integer> ids = collection.iterator();
                while (ids.hasNext()){
                    int partsId = ids.next();
                    ExportContractProductPartsEntity updateReq = new ExportContractProductPartsEntity();
                    //修改主键
                    updateReq.setId(partsId);
                    //修改时间
                    updateReq.setModifyTime(new Date());
                    //设为无效
                    updateReq.setValid(DataIsValidEnum.INVALID.getId());

                    exportContractProductPartsService.update(updateReq);

                }
            }
        }
    }

    /**
     * 新增主表信息
     * @param req 新增参数
     * @param creator 创建人
     * @param createNo 创建人编码
     * @return 主表id
     * @throws ParseException
     */
    private Integer insert(AddExportContractReq req, String creator, String createNo) throws ParseException {
        //初始化对象
        ExportContractEntity contract = new ExportContractEntity();
        //赋值
        BeanUtils.copyProperties(req, contract);
        //单号去前后空格
        contract.setBillNo(req.getBillNo().trim());
        //签约日期
        contract.setSigningDate(DateUtils.convertStringToDate(req.getSigningDate(), DateUtils.DATE_PATTERN));
        //出运日期
        contract.setCarryTime(DateUtils.convertStringToDate(req.getCarryTime(), DateUtils.DATE_PATTERN));
        //付款日期
        contract.setPaymentTerm(DateUtils.convertStringToDate(req.getPaymentTerm(), DateUtils.DATE_PATTERN));
        //设置数据有效性(0:无效 1:有效)
        contract.setValid(DataIsValidEnum.VALID.getId());

        if(null == req.getId()){
            //新增
            //保存后进草稿箱
            contract.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
            //设置创建人
            contract.setOperator(creator);
            //设置创建人编码
            contract.setOperationCode(createNo);
            //设置创建时间
            contract.setCreateDate(new Date());
            //调用接口新增调拨
            return exportContractService.insert(contract) == 1 ? contract.getId() : null;
        }else {
            //修改

            //如果明细、费用为空，则删除对应所有明细和费用
            if(CollectionUtils.isEmpty(req.getDetailList())){
                ExportContractProductEntity detailReq = new ExportContractProductEntity();
                //设置报价id
                detailReq.setParentId(req.getId());
                //数据有效
                detailReq.setValid(DataIsValidEnum.VALID.getId());
                List<ExportContractProductEntity> detailList = exportContractProductService.queryAll(detailReq);
                if(!CollectionUtils.isEmpty(detailList)){
                    for(ExportContractProductEntity detail : detailList){
                        ExportContractProductEntity updateReq = new ExportContractProductEntity();
                        //主键id
                        updateReq.setId(detail.getId());
                        //设为无效
                        updateReq.setValid(DataIsValidEnum.INVALID.getId());

                        exportContractProductService.update(updateReq);
                    }
                }
            }

            if(CollectionUtils.isEmpty(req.getCostList())){
                ExportContractCostEntity costReq = new ExportContractCostEntity();
                //设置id
                costReq.setParentId(req.getId());
                //数据有效
                costReq.setValid(DataIsValidEnum.VALID.getId());
                List<ExportContractCostEntity> costList = exportContractCostService.queryAll(costReq);
                if(!CollectionUtils.isEmpty(costList)){
                    for(ExportContractCostEntity cost : costList){
                        ExportContractCostEntity updateReq = new ExportContractCostEntity();
                        //主键id
                        updateReq.setId(cost.getId());
                        //修改时间
                        updateReq.setModifyTime(new Date());
                        //设为无效
                        updateReq.setValid(DataIsValidEnum.INVALID.getId());

                        exportContractCostService.update(updateReq);
                    }
                }
            }
            //设置修改时间
            contract.setModifyTime(new Date());

            //添加修改日志
            //获取修改前对象数据
            ExportContractEntity oldData = exportContractService.queryById(req.getId());
            BeanChangeLogUtil logUtil = new BeanChangeLogUtil();
            String info = logUtil.contrastObj(oldData, contract);
            if(StringUtils.isNotEmpty(info)) {
                //新增日志信息
                DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
                //模块主表id
                dataInfoLog.setParentId(req.getId());
                //模块id
                dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
                //操作人编码
                dataInfoLog.setOperationCode(createNo);
                //操作人名称
                dataInfoLog.setOperationName(creator);
                //操作类型
                dataInfoLog.setOperationType(OperationTypeEnum.UPDATE_DATA.getId());
                //操作时间
                dataInfoLog.setOperationTime(new Date());
                //操作内容
                dataInfoLog.setOperationContent("主信息:" + info);

                dataInfoLogService.insert(dataInfoLog);
            }

            return exportContractService.update(contract) == 1 ? contract.getId() : null;
        }

    }

    /**
     * 校验单号是否存在
     * @param billNo 单号
     * @return true:不重复 false:重复
     */
    private boolean checkRepeatBillNo(String billNo){
        ExportContractEntity req = new ExportContractEntity();
        req.setBillNo(billNo);
        req.setValid(DataIsValidEnum.VALID.getId());
        List<ExportContractEntity> contractEntities = exportContractService.queryAll(req);
        if(CollectionUtils.isEmpty(contractEntities)){
            return true;
        }
        return false;
    }

    /**
     * 获取外销信息
     * @param req 查询参数
     * @return 外销信息
     */
    public PageInfo<ExportContractPageListVo> getListByPage(ExportContractPageListReq req){
        //初始化回参对象集合
        List<ExportContractPageListVo> voList = new ArrayList<>();
        if(StringUtils.isBlank(req.getOperationCode()) && StringUtils.isBlank(req.getSalesmanCode()) && StringUtils.isBlank(req.getDeptOperationCode()) && StringUtils.isBlank(req.getDeptSalesmanCode())){
            PageInfo pageInfo = new PageInfo();
            pageInfo.setList(voList);
            return pageInfo;
        }
        //初始化查询对象
        ExportContractPageListInfoReq query = new ExportContractPageListInfoReq();
        //赋值
        BeanUtils.copyProperties(req, query);
        if(StringUtils.isNotEmpty(req.getBillNo())){
            //去掉前后空格
            query.setBillNo(req.getBillNo().trim());
        }
        if(null != req.getStatus() && 2 == req.getStatus()){
            query.setStatus(null);
            query.setStatusList(OperationStatusEnum.PENDING_BOX.getId() + "," + OperationStatusEnum.SECONDARY_APPROVAL.getId());
        }
        //调用接口查询结果
        List<ExportContractEntity> contractList = exportContractService.getExportContractListInfo(query);
        PageInfo pageInfo = new PageInfo(contractList);
        if(CollectionUtils.isEmpty(contractList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        for(ExportContractEntity contract : contractList){
            ExportContractPageListVo vo = new ExportContractPageListVo();
            //赋值
            BeanUtils.copyProperties(contract, vo);
            //签约日期
            vo.setSigningDate(DateUtils.format(contract.getSigningDate(), DateUtils.DATE_PATTERN));
            //出运日期
            vo.setCarryTime(DateUtils.format(contract.getCarryTime(), DateUtils.DATE_PATTERN));
            //付款期限
            vo.setPaymentTerm(DateUtils.format(contract.getPaymentTerm(), DateUtils.DATE_PATTERN));
            //状态
            vo.setStatusStr(OperationStatusEnum.getDescById(contract.getStatus()));
            //获取单据操作员所属部门编码
            UserEntity user = userService.selectUserByCode(contract.getOperationCode());
            vo.setDeptCode(user.getDepartmentCode());

            voList.add(vo);
        }

        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 获取外销信息
     * @param req 查询参数
     * @return 外销信息
     */
    public List<ExportContractPageListVo> getList(ExportContractPageListReq req){
        //初始化回参对象集合
        List<ExportContractPageListVo> voList = new ArrayList<>();
        //初始化查询对象
        ExportContractPageListInfoReq query = new ExportContractPageListInfoReq();
        //赋值
        BeanUtils.copyProperties(req, query);
        if(StringUtils.isNotEmpty(req.getBillNo())){
            //去掉前后空格
            query.setBillNo(req.getBillNo().trim());
        }
        //调用接口查询结果
        List<ExportContractEntity> contractList = exportContractService.getExportContractListInfo(query);
        if(CollectionUtils.isEmpty(contractList)){
            return voList;
        }
        for(ExportContractEntity contract : contractList){
            ExportContractPageListVo vo = new ExportContractPageListVo();
            //赋值
            BeanUtils.copyProperties(contract, vo);
            //签约日期
            vo.setSigningDate(DateUtils.format(contract.getSigningDate(), DateUtils.DATE_PATTERN));
            //出运日期
            vo.setCarryTime(DateUtils.format(contract.getCarryTime(), DateUtils.DATE_PATTERN));
            //付款期限
            vo.setPaymentTerm(DateUtils.format(contract.getPaymentTerm(), DateUtils.DATE_PATTERN));
            //状态
            vo.setStatusStr(OperationStatusEnum.getDescById(contract.getStatus()));

            voList.add(vo);
        }

        return voList;
    }

    /**
     * 详情
     * @param id 外销id
     * @return 外销详情
     */
    public ExportContractDetailVo detail(Integer id){
        //初始化回参对象
        ExportContractDetailVo vo = new ExportContractDetailVo();
        if(null == id){
            return vo;
        }
        //第一步：获取主表信息
        ExportContractEntity contract = exportContractService.queryById(id);
        if(null == contract || null == contract.getId()){
            return vo;
        }
        //赋值
        BeanUtils.copyProperties(contract, vo);
        //签约日期
        vo.setSigningDate(DateUtils.format(contract.getSigningDate(), DateUtils.DATE_PATTERN));
        //出运日期
        vo.setCarryTime(DateUtils.format(contract.getCarryTime(), DateUtils.DATE_PATTERN));
        //付款期限
        vo.setPaymentTerm(DateUtils.format(contract.getPaymentTerm(), DateUtils.DATE_PATTERN));
        //充值占用(0:否 1:是)
        //vo.setRechargeOccupancyStr(contract.getRechargeOccupancy() == 1 ? "是" : "否");
        //是否报关(0:否 1:是)
        vo.setIsDeclareStr(contract.getIsDeclare() == 1 ? "是" : "否");
        if(null != contract.getShipmentInBatches()){
            //分批出运(0:否 1:是)
            vo.setShipmentInBatchesStr(contract.getShipmentInBatches() == 1 ? "是" : "否");
        }
        if(null != contract.getWhetherToSupport()){
            //是否打托(0:否 1:是)
            vo.setWhetherToSupportStr(contract.getWhetherToSupport() == 1 ? "是" : "否");
        }
        if(null != contract.getWhetherToPurchase()){
            //是否采购(0:否 1:是)
            vo.setWhetherToPurchaseStr(contract.getWhetherToPurchase() == 1 ? "是" : "否");
        }
        if(null != contract.getWhetherCreditGuarantee()){
            //是否走信保订单(0:否 1:是(采购抬头：上海沣奇) 2:是(采购抬头：上海源铢))
            switch (contract.getWhetherCreditGuarantee()){
                case 1:
                    vo.setWhetherCreditGuaranteeStr("是(采购抬头：上海沣奇)");
                    break;
                case 2:
                    vo.setWhetherCreditGuaranteeStr("是(采购抬头：上海源铢)");
                    break;
                default:
                    vo.setWhetherCreditGuaranteeStr("否");
            }

        }
        if(null != contract.getShippingMark()){
            //唛头(0:否 1:是)
            vo.setShippingMarkStr(contract.getShippingMark() == 1 ? "是" : "否");
        }
        if(null != contract.getWhetherToReplenish()){
            //是否补货(0:否 1:是)
            vo.setWhetherToReplenishStr(contract.getWhetherToReplenish() == 1 ? "是" : "否");
        }
        if(null != contract.getModeOfTrade()){
            //瓶底是否指定Logo(1:不指定，2：指定光面，3：指定客户Logo，4：指定Rtco Logo)
            vo.setModeOfTradeStr(ModeOfTradeEnum.getDescById(contract.getModeOfTrade()));
        }
        //通过外销合同号获取已做计划数量
        int planCount = exportContractProductService.getPlanCountByContractNo(contract.getBillNo());
        vo.setUsedPlanCount(planCount);

        //第二步：获取产品明细数据
        ExportContractProductEntity contractDetailReq = new ExportContractProductEntity();
        //外销id
        contractDetailReq.setParentId(id);
        //有效数据
        contractDetailReq.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询产品明细数据
        List<ExportContractProductEntity> contractDetailList = exportContractProductService.queryAll(contractDetailReq);
        if(!CollectionUtils.isEmpty(contractDetailList)){
            //初始化回参对象集合
            List<ExportContractProductDetailVo> detailList = new ArrayList<>();
            for(ExportContractProductEntity detailEntity : contractDetailList){
                //初始化回参对象
                ExportContractProductDetailVo productDetailVo = new ExportContractProductDetailVo();
                //赋值
                BeanUtils.copyProperties(detailEntity, productDetailVo);
                //交货日期
                productDetailVo.setDeliveryDate(DateUtils.format(detailEntity.getDeliveryDate()));
                //校验该产品在下游是否被调用 true:未被调用 false:已被调用
                BigDecimal sum = getUsedQuantity(contract.getBillNo(), detailEntity.getProductCode(), detailEntity.getSpecificationCode(), detailEntity.getId());
                if(sum.compareTo(BigDecimal.ZERO) == 1){
                    //已被调用，不能删除
                    productDetailVo.setIsDelete(1);
                    //设置已被调用数量
                    productDetailVo.setUsedQuantity(sum);
                }else {
                    //未被调用，可删除
                    productDetailVo.setIsDelete(0);
                }
                //获取对应配件信息
                ExportContractProductPartsEntity partsReq = new ExportContractProductPartsEntity();
                //设置报价id
                partsReq.setParentId(id);
                //设置产品明细id
                partsReq.setDetailId(detailEntity.getId());
                //设置数据有效性
                partsReq.setValid(DataIsValidEnum.VALID.getId());
                //查询结果
                List<ExportContractProductPartsEntity> partsEntityList = exportContractProductPartsService.queryAll(partsReq);
                if(!CollectionUtils.isEmpty(partsEntityList)){
                    List<ExportContractProductPartsDetailVo> partsList = partsEntityList.stream().map(p ->{
                        ExportContractProductPartsDetailVo partsVo = new ExportContractProductPartsDetailVo();
                        //赋值
                        BeanUtils.copyProperties(p, partsVo);
                        return partsVo;
                    }).collect(Collectors.toList());

                    //添加相关配件集合
                    productDetailVo.setPartsList(partsList);
                }

                detailList.add(productDetailVo);
            }
            //添加产品明细数据
            vo.setDetailList(detailList);
        }

        //第三步：获取费用数据
        List<ExportContractCostDetailVo> costList = getExportContractCostByParentId(id);
        //添加相关费用信息
        vo.setCostList(costList);

        //第四步：获取对应附件信息
        AnnexEntity annex = new AnnexEntity();
        //设置模块id
        annex.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
        //设置父id
        annex.setParentId(id);
        //设置数据有效
        annex.setValid(DataIsValidEnum.VALID.getId());
        //调用接口查询附件信息
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if (!CollectionUtils.isEmpty(annexList)) {
            List<AnnexVo> annexVos = annexList.stream().map(p -> {
                AnnexVo annexVo = new AnnexVo();
                //赋值
                BeanUtils.copyProperties(p, annexVo);
                //上传时间转换
                annexVo.setUploadTime(DateUtils.format(p.getUploadTime(), DateUtils.DATE_TIME_PATTERN));
                //设置附件为旧附件,用以区分修改时附件状态
                annexVo.setNews(0);

                return annexVo;
            }).collect(Collectors.toList());

            vo.setAnnexList(annexVos);
        }

        //第五步：获取对应日志信息
        DataInfoLogEntity logReq = new DataInfoLogEntity();
        //主表id
        logReq.setParentId(id);
        //模块id
        logReq.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
        //查询结果
        List<DataInfoLogEntity> dataInfoLog = dataInfoLogService.queryAll(logReq);
        if(!CollectionUtils.isEmpty(dataInfoLog)){
            List<DataInfoLogVo> logVos = new ArrayList<>();
            for(DataInfoLogEntity log : dataInfoLog){
                DataInfoLogVo logVo = new DataInfoLogVo();
                //赋值
                BeanUtils.copyProperties(log, logVo);
                //日期处理
                logVo.setOperationTime(DateUtils.format(log.getOperationTime(), DateUtils.DATE_TIME_PATTERN));
                //操作类型
                logVo.setOperationType(OperationTypeEnum.getDescById(log.getOperationType()));

                logVos.add(logVo);
            }

            vo.setLogList(logVos);
        }

        return vo;
    }

    /**
     * 通过外销主表id获取费用信息
     * @param id 外销主表id
     * @return 费用信息
     */
    public List<ExportContractCostDetailVo> getExportContractCostByParentId(Integer id){
        ExportContractCostEntity costReq = new ExportContractCostEntity();
        //设置报价id
        costReq.setParentId(id);
        //获取有效数据
        costReq.setValid(DataIsValidEnum.VALID.getId());
        //查询结果
        List<ExportContractCostEntity> costEntities = exportContractCostService.queryAll(costReq);
        //初始化回参
        List<ExportContractCostDetailVo> costList = new ArrayList<>();
        if(CollectionUtils.isEmpty(costEntities)){
            return costList;
        }
        for(ExportContractCostEntity cost : costEntities){
            ExportContractCostDetailVo costVo = new ExportContractCostDetailVo();
            //赋值
            BeanUtils.copyProperties(cost, costVo);

            costList.add(costVo);
        }
        return costList;
    }

    /**
     * 通过外销主表ids获取费用信息
     * @return 费用信息
     */
    public List<ExportContractCostDetailVo> getExportContractCostByParentIds(List<Integer> idList){
        //查询结果
        List<ExportContractCostEntity> costEntities = exportContractCostService.queryAllBYIdList(idList);
        //初始化回参
        List<ExportContractCostDetailVo> costList = new ArrayList<>();
        if(CollectionUtils.isEmpty(costEntities)){
            return costList;
        }
        for(ExportContractCostEntity cost : costEntities){
            ExportContractCostDetailVo costVo = new ExportContractCostDetailVo();
            //赋值
            BeanUtils.copyProperties(cost, costVo);

            ExportContractEntity contractEntity = exportContractService.queryById(cost.getParentId());
            costVo.setContractNo(contractEntity.getBillNo());

            costList.add(costVo);
        }
        return costList;
    }

    /**
     * 删除
     * @param req
     */
    public void delete(OperationReq req){
        if(null == req.getId() || null == req.getStatus()){
            return;
        }
        ExportContractEntity contractReq = new ExportContractEntity();
        contractReq.setId(req.getId());
        contractReq.setModifyTime(new Date());
        if(req.getStatus().equals(OperationStatusEnum.DRAFT_BOX.getId())){
            //草稿箱删除,数位改为垃圾箱
            contractReq.setStatus(OperationStatusEnum.TRASH_CAN.getId());
            exportContractService.update(contractReq);
            return;
        }else {
            //垃圾箱删除,将主数据设为无效
            contractReq.setValid(DataIsValidEnum.INVALID.getId());
            exportContractService.update(contractReq);
        }
        //获取对应明细数据
        ExportContractProductEntity detailEntity = new ExportContractProductEntity();
        detailEntity.setParentId(req.getId());
        detailEntity.setValid(DataIsValidEnum.VALID.getId());

        List<ExportContractProductEntity> detailList = exportContractProductService.queryAll(detailEntity);
        if(CollectionUtils.isEmpty(detailList)){
            return;
        }
        //将所有对应有效的明细数据设为无效
        for(ExportContractProductEntity detail : detailList){
            ExportContractProductEntity detailReq = new ExportContractProductEntity();
            detailReq.setId(detail.getId());
            detailReq.setValid(DataIsValidEnum.INVALID.getId());

            exportContractProductService.update(detailReq);
        }

        //获取费用数据
        ExportContractCostEntity costEntity = new ExportContractCostEntity();
        costEntity.setParentId(req.getId());
        costEntity.setValid(DataIsValidEnum.VALID.getId());

        List<ExportContractCostEntity> costList = exportContractCostService.queryAll(costEntity);
        if(CollectionUtils.isEmpty(costList)){
            return;
        }
        //将所有对应有效的费用数据设为无效
        for(ExportContractCostEntity cost : costList){
            ExportContractCostEntity costReq = new ExportContractCostEntity();
            costReq.setId(cost.getId());
            costReq.setModifyTime(new Date());
            costReq.setValid(DataIsValidEnum.INVALID.getId());

            exportContractCostService.update(costReq);
        }

        //获取对应所有附件
        AnnexEntity annex = new AnnexEntity();
        annex.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
        annex.setParentId(req.getId());
        annex.setValid(DataIsValidEnum.VALID.getId());
        List<AnnexEntity> annexList = annexService.queryAll(annex);
        if(CollectionUtils.isEmpty(annexList)){
            return;
        }
        //删除所有对应的有效的附件
        for(AnnexEntity annexData : annexList){
            AnnexEntity annexReq = new AnnexEntity();
            annexReq.setId(annexData.getId());
            annexReq.setUpdateTime(new Date());
            annexReq.setValid(DataIsValidEnum.INVALID.getId());

            annexService.update(annexReq);
        }
    }

    /**
     * 收款首页-箱体操作
     * @param req
     */
    public R operation(OperationReq req, UserEntity user){
        String deptCode = user.getDepartmentCode();
        String msn = user.getMsn();
        if(null == req.getId() || null == req.getOperation() || StringUtils.isBlank(req.getBillNo())){
            return R.buildError(ResultStatusEnum.SYSTEM_ERROR);
        }
        ExportContractEntity exportContractEntity = new ExportContractEntity();
        //设置修改主键
        exportContractEntity.setId(req.getId());
        //修改时间
        exportContractEntity.setModifyTime(new Date());

        //新增日志信息
        DataInfoLogEntity dataInfoLog = new DataInfoLogEntity();
        //模块主表id
        dataInfoLog.setParentId(req.getId());
        //模块id
        dataInfoLog.setModuleId(ModuleTypeEnum.BUSINESS_EXPORT_CONTRACT.getId());
        //操作人编码
        dataInfoLog.setOperationCode(user.getCode());
        //操作人名称
        dataInfoLog.setOperationName(user.getName());
        //操作时间
        dataInfoLog.setOperationTime(new Date());
        //操作内容
        dataInfoLog.setOperationContent("单据操作");

        switch (req.getOperation()){
            case 1:
                //提交审批后
                if((deptCode.equals("NM001") || deptCode.equals("NM002")) && msn.equals("是")){
                    //内贸一组管理员 提交审批后 直接进入二级审批
                    exportContractEntity.setStatus(OperationStatusEnum.SECONDARY_APPROVAL.getId());
                }else if(deptCode.equals("GNSYB") && msn.equals("是")){
                    //国内事业部管理员 提交审批后 状态设为已批箱
                    exportContractEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                }else {
                    //状态为待批箱
                    exportContractEntity.setStatus(OperationStatusEnum.PENDING_BOX.getId());
                }
                break;
            case 2:
                //操作类型
                dataInfoLog.setOperationType(OperationTypeEnum.APPROVED_DATA.getId());
                if((deptCode.equals("NM001") || deptCode.equals("NM002")) && msn.equals("是")){
                    //内贸一组管理员 审批通过， 进入二级审批
                    exportContractEntity.setStatus(OperationStatusEnum.SECONDARY_APPROVAL.getId());
                }else if(deptCode.equals("GNSYB") && msn.equals("是")){
                    //国内事业部管理员 审批通过 状态设为已批箱
                    exportContractEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                }else {
                    //审批通过,状态设为已批箱
                    exportContractEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                }
                break;
            case 3:
                //审批退回
                //校验是否可以回退数据 1:采购调用 2:出运计划调用 3:调拨调用 0:未被调用
                Integer status = checkDataIsRollBack(req.getId(), req.getBillNo());
                if (0 == status || 1 == status) {
                    //外销做了采购可以审批退回
                    //状态设为草稿箱
                    exportContractEntity.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
                    //操作类型
                    dataInfoLog.setOperationType(OperationTypeEnum.APPROVAL_RETURNED_DATA.getId());
                } else if (3 == status) {
                    //调拨调用
                    return R.buildError(ResultStatusEnum.EXPORT_RETURNED_TRANSFER_FAILED);
                } else {
                    //审批退回失败,存在已被调用的产品
                    return R.buildError(ResultStatusEnum.APPROVAL_RETURNED_FAILED);
                }
                break;
            case 4:
                //将状态设为完成
                exportContractEntity.setStatus(OperationStatusEnum.COMPLETION_BOX.getId());
                //操作类型
                dataInfoLog.setOperationType(OperationTypeEnum.CONSUMMATION_DATA.getId());
                break;
            case 5:
                //点击还原，将状态改为草稿箱
                exportContractEntity.setStatus(OperationStatusEnum.DRAFT_BOX.getId());
                break;
            case 6:
                //点击终止，将状态改为终止箱
                //校验是否可以终止数据1.出运计划调用 2.收款 3.库存
                Integer usedStatus = checkDataIsTermination(req.getId(), req.getBillNo());
                switch (usedStatus){
                    case 0:
                        //状态设为终止箱
                        exportContractEntity.setStatus(OperationStatusEnum.TERMINATION_BOX.getId());
                        //操作类型
                        dataInfoLog.setOperationType(OperationTypeEnum.STOP_DATA.getId());
                        break;
                    case 1:
                        //出运计划调用
                        return R.buildError(ResultStatusEnum.PLAN_USED);
                    case 2:
                        //收款调用
                        return R.buildError(ResultStatusEnum.COLLECTION_USED);
                    case 3:
                        //库存调用
                        return R.buildError(ResultStatusEnum.STOCK_USED);
                }
                break;
            case 7:
                //取消终止，将状态改为已批箱
                exportContractEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                break;
        }
        //调用接口修改
        exportContractService.update(exportContractEntity);

        dataInfoLogService.insert(dataInfoLog);

        return R.buildError(ResultStatusEnum.SUCCESS);
    }

    /**
     * 校验该外销是否被下游调用 1.出运计划调用 2.收款 3.库存 0:未被调用
     * @param id 外销主ID
     * @param billNo 外销合同号
     * @return 该外销是否被下游调用 1.出运计划调用 2.收款 3.库存 0:未被调用
     */
    private int checkDataIsTermination(Integer id, String billNo){
        ExportContractProductEntity exportContractProductReq = new ExportContractProductEntity();
        //设置父id
        exportContractProductReq.setParentId(id);
        //设置数据有效
        exportContractProductReq.setValid(DataIsValidEnum.VALID.getId());
        //获取报价产品信息
        List<ExportContractProductEntity> detailList = exportContractProductService.queryAll(exportContractProductReq);
        if(CollectionUtils.isEmpty(detailList)){
            return 0;
        }
        for(ExportContractProductEntity detail : detailList){
            //校验该产品在下游是否被调用 1.出运计划调用 2.收款 3.库存 0:未被调用
            //调用接口查询该产品在出运计划中的数量
            int count = shipmentPlanService.getPlanProductNum(billNo, detail.getProductCode(), detail.getSpecificationCode(), detail.getId());
            if(count > 0){
                return 1;
            }
        }
        List<ReceivePaymentEntity> collectionList = receivePaymentService.getCollectionByContractNo(billNo);
        if(!CollectionUtils.isEmpty(collectionList)){
            return 2;
        }
        StockReq stockReq = new StockReq();
        stockReq.setContractNo(billNo);
        stockReq.setLikeContractNo(1);
        List<StockEntity> stockList = stockService.getStockList(stockReq);
        if(!CollectionUtils.isEmpty(stockList)){
            return 3;
        }
        return 0;
    }

    /**
     * 批量操作
     * @param req 操作数据实体
     * @param msn 是否管理层
     * @return 批量操作结果
     */
    public R batchOperation(BatchOperationReq req, String msn){
        if(!"是".equals(msn)){
            return R.buildError(ResultStatusEnum.INSUFFICIENT_PERMISSION_ERROR);
        }
        if(CollectionUtils.isEmpty(req.getOperationReqs())){
            return R.buildError(ResultStatusEnum.SUCCESS);
        }
        switch (req.getType()){
            case 1:
                for(OperationReq operationReq : req.getOperationReqs()){
                    if(OperationStatusEnum.DRAFT_BOX.getId() == operationReq.getStatus()){
                        ExportContractEntity exportContractEntity = new ExportContractEntity();
                        //设置修改主键
                        exportContractEntity.setId(operationReq.getId());
                        //修改时间
                        exportContractEntity.setModifyTime(new Date());
                        //提交审批后,状态为待批箱
                        exportContractEntity.setStatus(OperationStatusEnum.PENDING_BOX.getId());
                        //调用接口修改
                        exportContractService.update(exportContractEntity);
                    }
                }
                break;
            case 2:
                for(OperationReq operationReq : req.getOperationReqs()){
                    if(OperationStatusEnum.PENDING_BOX.getId() == operationReq.getStatus()){
                        ExportContractEntity exportContractEntity = new ExportContractEntity();
                        //设置修改主键
                        exportContractEntity.setId(operationReq.getId());
                        //修改时间
                        exportContractEntity.setModifyTime(new Date());
                        //审批通过,状态设为已批箱
                        exportContractEntity.setStatus(OperationStatusEnum.APPROVED_BOX.getId());
                        //调用接口修改
                        exportContractService.update(exportContractEntity);
                    }
                }
                break;
            default:
                break;
        }
        return R.buildError(ResultStatusEnum.SUCCESS);
    }

    /**
     * 校验是否可以回退数据 1:采购调用 2:出运计划调用 0:未被调用
     * @param id 报价id
     * @param billNo 报价单号
     * @return 是否可以回退数据: 1:采购调用 2:出运计划调用 0:未被调用
     */
    public Integer checkDataIsRollBack(Integer id, String billNo){
        ExportContractProductEntity exportContractProductReq = new ExportContractProductEntity();
        //设置父id
        exportContractProductReq.setParentId(id);
        //设置数据有效
        exportContractProductReq.setValid(DataIsValidEnum.VALID.getId());
        //获取报价产品信息
        List<ExportContractProductEntity> detailList = exportContractProductService.queryAll(exportContractProductReq);
        if(CollectionUtils.isEmpty(detailList)){
            return 0;
        }
        for(ExportContractProductEntity detail : detailList){
            //校验该产品在下游是否被调用 1:采购调用 2:出运计划调用 3:调拨调用 0:未被调用
            Integer status = checkProductIsUsed(billNo, detail.getProductCode(), detail.getSpecificationCode(), detail.getId());
            return status;

        }
        return 0;
    }


    /**
     * 获取下游调用情况
     *
     * @param id     外销ID
     * @param billNo 外销单号
     * @return 下游调用情况: 1:采购调用 2:出运计划调用 0:未被调用
     */
    public Integer getUsedInfoByConcatNo(Integer id, String billNo) {
        ExportContractProductEntity exportContractProductReq = new ExportContractProductEntity();
        //设置父id
        exportContractProductReq.setParentId(id);
        //设置数据有效
        exportContractProductReq.setValid(DataIsValidEnum.VALID.getId());
        //获取报价产品信息
        List<ExportContractProductEntity> detailList = exportContractProductService.queryAll(exportContractProductReq);
        if (CollectionUtils.isEmpty(detailList)) {
            return 0;
        }

        //通过外销合同号获取已做采购数量
        int purchaseCount = exportContractProductService.getUsedPurchaseInfoByConcatNo(billNo);
        if (purchaseCount > 0) {
            return 1;
        }

        //通过外销合同号获取已做计划数量
        int planCount = exportContractProductService.getPlanCountByContractNo(billNo);
        if (planCount > 0) {
            return 2;
        }
        return 0;
    }

    /**
     * 批量修改单据业务员
     * @param req 修改信息
     * @return
     */
    public R batchUpdateSalesman(BatchOperationReq req){
        //业务员名称
        String salesmanName = req.getSalesmanNameUpdate();
        //业务员编码
        String salesmanCode = req.getSalesmanCodeUpdate();
        if(StringUtils.isEmpty(salesmanCode) || StringUtils.isEmpty(salesmanName)){
            return R.buildError(ResultStatusEnum.EXPORT_UPDATE_SALESMAN_IS_NULL);
        }
        if(CollectionUtils.isEmpty(req.getOperationReqs())){
            return R.build("");
        }
        for(OperationReq info : req.getOperationReqs()){
            ExportContractEntity contractReq = new ExportContractEntity();
            contractReq.setId(info.getId());
            contractReq.setSalesmanName(salesmanName);
            contractReq.setSalesmanCode(salesmanCode);
            contractReq.setModifyTime(new Date());

            exportContractService.update(contractReq);
        }
        return R.build(ResultStatusEnum.SUCCESS);
    }

    /**
     * 获取外销主表信息
     * @param req 查询条件入参实体
     * @return 外销主表信息
     */
    public PageInfo<ImportExportContractVo> getContractByPage(ImportExportContractReq req){
        //初始化回参对象集合
        List<ImportExportContractVo> voList = new ArrayList<>();
        if(StringUtils.isBlank(req.getBillNo()) &&
                StringUtils.isBlank(req.getCustomerContactNo()) &&
                StringUtils.isBlank(req.getCustomerName()) &&
                StringUtils.isBlank(req.getSigningDateEnd()) &&
                StringUtils.isBlank(req.getSigningDateStart()) &&
                StringUtils.isBlank(req.getDeptSalesmanCode()) &&
                null == req.getIsDeclare()){
            PageInfo pageInfo = new PageInfo();
            pageInfo.setList(voList);
            return pageInfo;

        }
        //初始化查询对象
        ImportExportContractInfoReq queryReq = new ImportExportContractInfoReq();
        //字段赋值
        BeanUtils.copyProperties(req, queryReq);
        //调用接口查询结果
        List<ExportContractEntity> resList = exportContractService.queryImportContractInfo(queryReq);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(resList);
        if(CollectionUtils.isEmpty(resList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        for(ExportContractEntity res : resList){
            //初始化回参对象
            ImportExportContractVo vo = new ImportExportContractVo();
            //字段赋值
            BeanUtils.copyProperties(res, vo);
            //签约日期
            vo.setSigningDate(DateUtils.format(res.getSigningDate(), DateUtils.DATE_PATTERN));
            //出运日期
            vo.setCarryTime(DateUtils.format(res.getCarryTime(), DateUtils.DATE_PATTERN));
            //付款期限
            vo.setPaymentTerm(DateUtils.format(res.getPaymentTerm(), DateUtils.DATE_PATTERN));

            voList.add(vo);
        }
        pageInfo.setList(voList);

        return pageInfo;
    }

    /**
     * 获取外销产品信息
     * @param id 外销主表id
     * @return 外销产品信息
     */
    public PageInfo<ImportExportContractProductVo> getContractProductByPage(Integer id){
        //调用接口查询结果
        List<ImportExportContractProductRsp> resList = exportContractProductService.queryByParentId(id);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(resList);
        //初始化回参对象集合
        List<ImportExportContractProductVo> voList = new ArrayList<>();
        if(CollectionUtils.isEmpty(resList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        pageInfo.setList(getContractProductInfo(resList));

        return pageInfo;
    }

    /**
     * 获取外销产品信息
     * @param id 外销主表id
     * @return 外销产品信息
     */
    public List<ImportExportContractProductVo> getContractProduct(Integer id){
        //调用接口查询结果
        List<ImportExportContractProductRsp> resList = exportContractProductService.queryByParentId(id);
        //初始化回参对象集合
        List<ImportExportContractProductVo> voList = new ArrayList<>();
        if(CollectionUtils.isEmpty(resList)){
            return voList;
        }
        return getContractProductInfo(resList);
    }

    /**
     * 处理外销产品信息
     * @param resList 外销产品信息
     * @return 外销产品信息
     */
    private List<ImportExportContractProductVo> getContractProductInfo(List<ImportExportContractProductRsp> resList){
        //初始化回参对象集合
        List<ImportExportContractProductVo> voList = new ArrayList<>();
        for(ImportExportContractProductRsp res : resList){
            //获取该外销单据已做过的出运计划数量
            // int count = shipmentPlanService.getPlanProduct(res.getSalesContractNo(), res.getProductCode(), res.getSpecificationCode());
            int count = shipmentPlanService.getPlanProductNum(res.getBillNo(), res.getProductCode(), res.getSpecificationCode(), res.getId());

            BigDecimal newCount = new BigDecimal(Integer.toString(count));
            //获取当前单据产品数量
            BigDecimal productNum = res.getProductNum();
            //剩余数量
            BigDecimal resCount = productNum.subtract(newCount);
            if(resCount.compareTo(BigDecimal.ZERO) == 1){
                //获取剩余数量大于零数据
                //初始化回参对象
                ImportExportContractProductVo vo = new ImportExportContractProductVo();
                //字段赋值
                BeanUtils.copyProperties(res, vo);
                //新的数量
                vo.setProductNum(resCount);
                //剩余数量
                vo.setProductSurplusNum(resCount);

                voList.add(vo);
            }

        }
        return voList;
    }

    /**
     * 获取外销产品配件信息
     * @param id 外销产品id
     * @return 外销产品配件信息
     */
    public PageInfo<ImportExportContractProductPartsVo> getContractProductPartsByPage(Integer id){
        //调用接口查询结果
        List<ImportExportContractProductPartsRsp> resList = exportContractProductPartsService.queryByParentId(id);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(resList);
        //初始化回参对象集合
        List<ImportExportContractProductPartsVo> voList = new ArrayList<>();
        if(CollectionUtils.isEmpty(resList)){
            pageInfo.setList(voList);
            return pageInfo;
        }

        pageInfo.setList(getPartsInfo(resList));
        return pageInfo;
    }

    /**
     * 获取外销产品配件信息
     * @param id 外销产品id
     * @return 外销产品配件信息
     */
    public List<ImportExportContractProductPartsVo> getContractProductParts(Integer id){
        //调用接口查询结果
        List<ImportExportContractProductPartsRsp> resList = exportContractProductPartsService.queryByParentId(id);
        //初始化回参对象集合
        List<ImportExportContractProductPartsVo> voList = new ArrayList<>();
        if(CollectionUtils.isEmpty(resList)){
            return voList;
        }

        return getPartsInfo(resList);
    }

    /**
     * 处理外销配件信息
     * @param resList 外销配件信息
     * @return  处理外销配件信息
     */
    private List<ImportExportContractProductPartsVo> getPartsInfo(List<ImportExportContractProductPartsRsp> resList){
        //初始化回参对象集合
        List<ImportExportContractProductPartsVo> voList = new ArrayList<>();
        BigDecimal sumPrice = new BigDecimal("0");
        for(ImportExportContractProductPartsRsp res : resList){
            //初始化回参对象
            ImportExportContractProductPartsVo vo = new ImportExportContractProductPartsVo();
            //计算配件成本
            if(StringUtil.isNotEmpty(res.getPrice())){
                sumPrice = sumPrice.add(res.getPrice());
            }
            //字段赋值
            BeanUtils.copyProperties(res, vo);

            voList.add(vo);
        }
        for(ImportExportContractProductPartsVo partsVo : voList){
            partsVo.setPrice(sumPrice);
        }

        return voList;
    }

    /**
     * 获取外销产品配件信息
     * @param id 外销产品id
     * @return 外销产品配件信息
     */
    public List<ImportExportContractProductPartsRsp> getContractProductPartsById(Integer id){
        //调用接口查询结果
        List<ImportExportContractProductPartsRsp> resList = exportContractProductPartsService.queryByParentId(id);


        return resList;
    }

    /**
     * 获取外销产品表中存在指定报价单中的产品数量
     * @param req 查询条件
     * @return 外销产品表中存在指定报价单中的产品数量
     */
    public BigDecimal getRemainingQuantity(RemainingQuantityInfoReq req){
        //初始化查询参数
        RemainingQuantityReq queryReq = new RemainingQuantityReq();
        BeanUtils.copyProperties(req, queryReq);

        //调用接口查询
        List<ExportContractProductEntity> quantityList = exportContractProductService.getOfferRemainingQuantity(queryReq);
        //总数量
        BigDecimal sum = new BigDecimal("0");
        for(ExportContractProductEntity quantity : quantityList){
            if(StringUtil.isNotEmpty(quantity.getProductNum())){
                sum = sum.add(quantity.getProductNum());
            }
        }
        return sum;
    }

    /**
     * 获取库存现状
     * @param productCode 产品编码
     * @param specificationCode 规格编码
     * @return 库存现状
     */
    public PageInfo<StockInfoVo> getInventoryStatus(String productCode, String specificationCode){
        //初始化回参对象集合
        List<StockInfoVo> infoVos = new ArrayList<>();
        //初始化查询参数
        StockEntity req = new StockEntity();
        //设置产品编码
        req.setProductCode(productCode);
        //设置规格编码
        req.setSpecificationCode(specificationCode);
        //调用接口查询结果
        List<StockEntity> stockList = stockService.getStockListByStock(req);
        //获取分页信息
        PageInfo pageInfo = new PageInfo(stockList);
        if(CollectionUtils.isEmpty(stockList)){
            pageInfo.setList(infoVos);
            return pageInfo;
        }
        for(StockEntity stock : stockList){
            StockInfoVo vo = new StockInfoVo();
            //字段赋值
            BeanUtils.copyProperties(stock, vo);
            //设置合同类型
            vo.setContractTypeStr(ContractTypeEnum.getDescById(stock.getContractType()));

            infoVos.add(vo);
        }

        pageInfo.setList(infoVos);
        return pageInfo;
    }

    /**
     * 校验该产品在下游是否被调用
     * @param billNo 外销合同号
     * @param productCode 产品编码
     * @param specificationCode 规格编码
     * @param detailId 明细id
     * @return 1:采购调用 2:出运计划调用 3:调拨调用 0:未被调用
     */
    private Integer checkProductIsUsed(String billNo, String productCode, String specificationCode, Integer detailId){
        //初始化查询参数
        RemainingQuantityReq req = new RemainingQuantityReq();
        //外销合同号
        req.setBillNo(billNo);
        //产品编码
        req.setProductCode(productCode);
        //规格编码
        req.setSpecificationCode(specificationCode);
        //调用接口查询该产品在采购中的数量
        BigDecimal sumPurchase = exportContractProductService.getPurchaseInfo(req);
        if(sumPurchase.compareTo(BigDecimal.ZERO) == 1){
            return 1;
        }

        //调用接口查询该产品在出运计划中的数量
        int count = shipmentPlanService.getPlanProductNum(billNo, productCode, specificationCode, detailId);
        if(count > 0){
            return 2;
        }

        //查询调拨记录
        BigDecimal transferQuantity = transferDetailService.getTransferQuantityByConcatNo(billNo);
        boolean transferFlag = transferQuantity.compareTo(BigDecimal.ZERO) == 0;
        if(!transferFlag){
            //调拨调用
            return 3;
        }

        //未被调用
        return 0;
    }

    /**
     * 获取被下游调用的产品数量
     * @param billNo 外销合同号
     * @param productCode 产品编码
     * @param specificationCode 规格编码
     * @param detailId 明细id
     * @return 下游调用的产品数量
     */
    private BigDecimal getUsedQuantity(String billNo, String productCode, String specificationCode, Integer detailId){
        //初始化查询参数
        RemainingQuantityReq req = new RemainingQuantityReq();
        //报价单号
        req.setBillNo(billNo);
        //产品编码
        req.setProductCode(productCode);
        //规格编码
        req.setSpecificationCode(specificationCode);
        //调用接口查询该产品在采购中的数量
        BigDecimal sumPurchase = exportContractProductService.getPurchaseInfo(req);
        if(sumPurchase.compareTo(BigDecimal.ZERO) == 1){
            return sumPurchase;
        }

        //调用接口查询该产品在出运计划中的数量
        int count = shipmentPlanService.getPlanProductNum(billNo, productCode, specificationCode, detailId);
        if(count > 0){
            return new BigDecimal(String.valueOf(count));
        }

        return new BigDecimal("0");
    }


    /**
     * 统计1
     * @param req 查询条件
     * @return 统计1
     */
    public PageInfo<ContractStatisticsOneVo> getContractStatisticsOne(ContractStatisticsOneReq req){
        //调用接口查询
        List<ContractStatisticsOneRsp> statisticsList = exportContractService.getContractStatisticsOne(req);
        //初始化回参对象集合
        List<ContractStatisticsOneVo> voList = new ArrayList<>();
        PageInfo pageInfo = new PageInfo(statisticsList);
        if(CollectionUtils.isEmpty(statisticsList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        voList = getContractStatisticsOneInfo(statisticsList);

        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 统计1 导出Excel
     * @param req 查询条件
     * @return 统计1 导出Excel
     */
    public JSONObject getContractStatisticsOneInfo(ContractStatisticsOneReq req){
        //调用接口查询
        List<ContractStatisticsOneRsp> statisticsList = exportContractService.getContractStatisticsOne(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleInfoOfOneStatistics();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(statisticsList)){
            obj.put("data", data);
            return obj;
        }
        List<ContractStatisticsOneVo> voList = getContractStatisticsOneInfo(statisticsList);

        //封装数据
        getOneStatisticsInfo(data, voList);

        obj.put("data", data);
        return obj;
    }

    /**
     * 处理获取的外销信息
     * @param statisticsList 外销信息
     * @return
     */
    private List<ContractStatisticsOneVo> getContractStatisticsOneInfo(List<ContractStatisticsOneRsp> statisticsList){
        //初始化回参对象集合
        List<ContractStatisticsOneVo> voList = new ArrayList<>();
        //查询是否成交
        for(ContractStatisticsOneRsp statisticsRsp : statisticsList){
            //初始化回参对象
            ContractStatisticsOneVo vo = new ContractStatisticsOneVo();
            //赋值
            BeanUtils.copyProperties(statisticsRsp, vo);
            //签约日期
            vo.setSigningDate(DateUtils.format(statisticsRsp.getSigningDate()));
            //出运日期
            vo.setCarryTime(DateUtils.format(statisticsRsp.getCarryTime()));
            //合同总额
            BigDecimal totalContractAmount = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getTotalContractAmount())){
                totalContractAmount = statisticsRsp.getTotalContractAmount();
            }
            //美金汇率
            BigDecimal usdRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getUsdRate())){
                usdRate = statisticsRsp.getUsdRate();
            }
//            //USD合同总额
//            vo.setTotalContractAmountUSD(totalContractAmount.multiply(usdRate));
            //rmb汇率
            BigDecimal rmbRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getRmbRate())){
                rmbRate = statisticsRsp.getRmbRate();
            }
//            //RMB合同总额
//            if("usd-001".equals(statisticsRsp.getCurrency()) || "rmb-001".equals(statisticsRsp.getCurrency())){
//                vo.setTotalContractAmountRMB(totalContractAmount.multiply(rmbRate));
//            }else {
//                vo.setTotalContractAmountRMB(totalContractAmount.multiply(usdRate).multiply(rmbRate));
//            }


            if (statisticsRsp.getCurrency().equals("人民币") || statisticsRsp.getCurrency().equals("RMB")) {
                if(usdRate.compareTo(BigDecimal.valueOf(1)) == 1){
                    vo.setTotalContractAmountUSD(totalContractAmount.divide(usdRate, 2, BigDecimal.ROUND_HALF_UP));
                }else{
                    vo.setTotalContractAmountUSD(totalContractAmount.multiply(usdRate).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
                }
                vo.setTotalContractAmountRMB(totalContractAmount);

            }else {
                BigDecimal amountMultiply = totalContractAmount.multiply(usdRate);
                vo.setTotalContractAmountUSD(amountMultiply.divide(BigDecimal.valueOf(1),2,BigDecimal.ROUND_HALF_UP));
                vo.setTotalContractAmountRMB(amountMultiply.multiply(rmbRate).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
            }

            //初始化查询条件
            ReceivePaymentDetailEntity exportReq = new ReceivePaymentDetailEntity();
            //有效
            exportReq.setValid(DataIsValidEnum.VALID.getId());
            //销售合同号
            exportReq.setContractNo(statisticsRsp.getBillNo());
            //调用接口查询结果
            List<ReceivePaymentDetailEntity> contractList = receivePaymentDetailService.queryAll(exportReq);
            BigDecimal sum = new BigDecimal("0");
            if(!CollectionUtils.isEmpty(contractList)){
                for(ReceivePaymentDetailEntity tail : contractList){
                    //收汇金额
                    BigDecimal collectionAmount = new BigDecimal("0");
                    if(StringUtil.isNotEmpty(tail.getCollectionAmount())){
                        collectionAmount = tail.getCollectionAmount();
                    }
                    sum = sum.add(collectionAmount);
                }
            }
            //已收款金额
            vo.setAmountReceived(sum);
            //未收款金额
            vo.setUnAmountReceived(totalContractAmount.subtract(sum));

            voList.add(vo);
        }

        return voList;
    }

    /**
     * 封装数据
     * @param data 封装后数据
     * @param voList 原始数据
     */
    private void getOneStatisticsInfo(JSONArray data, List<ContractStatisticsOneVo> voList){
        BigDecimal amountUSD = new BigDecimal("0");
        BigDecimal amountRMB = new BigDecimal("0");
        BigDecimal amountReceived = new BigDecimal("0");
        BigDecimal unAmountReceived = new BigDecimal("0");
        for(ContractStatisticsOneVo vo : voList){
            JSONArray infoList = new JSONArray();
            infoList.add(getNotNullOfStringInfo(vo.getBillNo()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerName()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerContactNo()));
            infoList.add(vo.getSigningDate() == null ? "" : vo.getSigningDate());
            infoList.add(getNotNullOfStringInfo(vo.getSigningCompanyName()));
            infoList.add(getNotNullOfStringInfo(vo.getTransitPlaceName()));
            infoList.add(getNotNullOfStringInfo(vo.getDestinationName()));
            infoList.add(getNotNullOfStringInfo(vo.getCurrency()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getRmbRate()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUsdRate()));
            infoList.add(vo.getCarryTime() == null ? "" : vo.getCarryTime());
            infoList.add(getNotNullOfStringInfo(vo.getPriceTermsName()));
            infoList.add(getNotNullOfStringInfo(vo.getPaymentTypeName()));
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanName()));
            infoList.add(getNotNullOfStringInfo(vo.getBusinessModelName()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerAccountingPeriod()));
            infoList.add(getNotNullOfStringInfo(vo.getOperator()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getAdvancePaymentRatio()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getAdvancePaymentAmount()));
            if(StringUtil.isNotEmpty(vo.getTotalContractAmountUSD())){
                amountUSD = amountUSD.add(vo.getTotalContractAmountUSD());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalContractAmountUSD()));

            if(StringUtil.isNotEmpty(vo.getTotalContractAmountRMB())){
                amountRMB = amountRMB.add(vo.getTotalContractAmountRMB());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalContractAmountRMB()));

            if(StringUtil.isNotEmpty(vo.getAmountReceived())){
                amountReceived = amountReceived.add(vo.getAmountReceived());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getAmountReceived()));

            if(StringUtil.isNotEmpty(vo.getUnAmountReceived())){
                unAmountReceived = unAmountReceived.add(vo.getUnAmountReceived());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUnAmountReceived()));
            infoList.add(getNotNullOfStringInfo(vo.getMemo()));

            data.add(infoList);
        }
        //合计
        JSONArray customerInfoList = new JSONArray();
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add("");
        customerInfoList.add(amountUSD);
        customerInfoList.add(amountRMB);
        customerInfoList.add(amountReceived);
        customerInfoList.add(unAmountReceived);
        customerInfoList.add("");

        data.add(customerInfoList);

    }

    /**
     * 获取String类型不为空数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private String getNotNullOfStringInfo(String value){
        if(StringUtils.isEmpty(value)){
            return "";
        }else {
            return value;
        }
    }

    /**
     * 获取BigDecimal类型不为空的数据
     * @param value 目标数据
     * @return 不为空数据
     */
    private BigDecimal getNotNullOfBigDecimalInfo(BigDecimal value){
        if(StringUtil.isNotEmpty(value)){
            return value;
        }else {
            return new BigDecimal("0");
        }
    }

    /**
     * 获取excel的title信息
     * @return excel的title信息
     */
    private JSONArray getTitleInfoOfOneStatistics(){
        JSONArray titleList = new JSONArray();
        titleList.add("合同编号");
        titleList.add("客户名称");
        titleList.add("客户合同号");
        titleList.add("签约日期");
        titleList.add("签约公司");
        titleList.add("起运地");
        titleList.add("目的地");
        titleList.add("币种");
        titleList.add("人民币汇率");
        titleList.add("美元汇率");
        titleList.add("出运日期");
        titleList.add("价格术语");
        titleList.add("付款类型");
        titleList.add("业务员");
        titleList.add("业务模式");
        titleList.add("客户账期");
        titleList.add("操作员");
        titleList.add("预收款比例");
        titleList.add("预收款金额");
        titleList.add("USD合同总额");
        titleList.add("RMB合同总额");
        titleList.add("已收款金额");
        titleList.add("未收款金额");
        titleList.add("备注");

        return titleList;
    }

    /**
     * 统计2
     * @param req 查询条件
     * @return 统计2
     */
    public PageInfo<ContractStatisticsTwoVo> getContractStatisticsTwo(ContractStatisticsTwoReq req){
        //调用接口查询
        List<ContractStatisticsTwoRsp> statisticsList = exportContractService.getContractStatisticsTwo(req);
        //初始化回参对象集合
        List<ContractStatisticsTwoVo> voList = new ArrayList<>();
        PageInfo pageInfo = new PageInfo(statisticsList);
        if(CollectionUtils.isEmpty(statisticsList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        voList = getContractStatisticsTwoInfo(statisticsList);

        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 统计2 导出Excel
     * @param req 查询条件
     * @return 统计2 导出Excel
     */
    public JSONObject getContractStatisticsTwoInfo(ContractStatisticsTwoReq req){
        //调用接口查询
        List<ContractStatisticsTwoRsp> statisticsList = exportContractService.getContractStatisticsTwo(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleInfoOfTwoStatistics();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(statisticsList)){
            obj.put("data", data);
            return obj;
        }
        List<ContractStatisticsTwoVo> voList = getContractStatisticsTwoInfo(statisticsList);

        //封装数据
        getTwoStatisticsInfo(data, voList);

        obj.put("data", data);
        return obj;
    }

    /**
     * 封装数据 统计2
     * @param data 封装后数据
     * @param voList 原始数据
     */
    private void getTwoStatisticsInfo(JSONArray data, List<ContractStatisticsTwoVo> voList){
        BigDecimal productNum = new BigDecimal("0");
        BigDecimal moneySubtotalUSD = new BigDecimal("0");
        BigDecimal moneySubtotalRMB = new BigDecimal("0");
        BigDecimal carryNum = new BigDecimal("0");
        BigDecimal carryDetailNum = new BigDecimal("0");
        BigDecimal lastNum = new BigDecimal("0");
        BigDecimal lastNumOfDetail = new BigDecimal("0");
        for(ContractStatisticsTwoVo vo : voList){
            JSONArray infoList = new JSONArray();
            infoList.add(getNotNullOfStringInfo(vo.getBillNo()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerName()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerCode()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerContactNo()));
            infoList.add(vo.getSigningDate() == null ? "" : vo.getSigningDate());
            infoList.add(getNotNullOfStringInfo(vo.getProductCode()));
            infoList.add(getNotNullOfStringInfo(vo.getSpecificationCode()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCname()));
            if(StringUtil.isNotEmpty(vo.getProductNum())){
                productNum = productNum.add(vo.getProductNum());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getProductNum()));

            infoList.add(getNotNullOfBigDecimalInfo(vo.getUnitPrice()));
            if(StringUtil.isNotEmpty(vo.getMoneySubtotalUSD())){
                moneySubtotalUSD = moneySubtotalUSD.add(vo.getMoneySubtotalUSD());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getMoneySubtotalUSD()));

            if(StringUtil.isNotEmpty(vo.getMoneySubtotalRMB())){
                moneySubtotalRMB = moneySubtotalRMB.add(vo.getMoneySubtotalRMB());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getMoneySubtotalRMB()));

            if(StringUtil.isNotEmpty(vo.getCarryNum())){
                carryNum = carryNum.add(vo.getCarryNum());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getCarryNum()));

            if(StringUtil.isNotEmpty(vo.getCarryDetailNum())){
                carryDetailNum = carryDetailNum.add(vo.getCarryDetailNum());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getCarryDetailNum()));

            if(StringUtil.isNotEmpty(vo.getLastNum())){
                lastNum = lastNum.add(vo.getLastNum());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getLastNum()));

            if(StringUtil.isNotEmpty(vo.getLastNumOfDetail())){
                lastNumOfDetail = lastNumOfDetail.add(vo.getLastNumOfDetail());
            }
            infoList.add(getNotNullOfBigDecimalInfo(vo.getLastNumOfDetail()));

            infoList.add(getNotNullOfStringInfo(vo.getCarryStatus()));
            infoList.add(getNotNullOfStringInfo(vo.getSigningCompanyName()));
            infoList.add(getNotNullOfStringInfo(vo.getCurrency()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getRmbRate()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUsdRate()));
            infoList.add(getNotNullOfStringInfo(vo.getPriceTermsName()));
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanName()));
            infoList.add(getNotNullOfStringInfo(vo.getOperator()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerAccountingPeriod()));

            infoList.add(getNotNullOfStringInfo(vo.getProductCDesc()));
            infoList.add(getNotNullOfStringInfo(vo.getProductEDesc()));

            infoList.add(getNotNullOfStringInfo(vo.getPaymentTypeName()));
            infoList.add(getNotNullOfStringInfo(vo.getIsDeclareStr()));
            infoList.add(getNotNullOfStringInfo(vo.getContainerType()));
            infoList.add(getNotNullOfStringInfo(vo.getModeOfTradeStr()));
            infoList.add(getNotNullOfStringInfo(vo.getMemo()));
            infoList.add(getNotNullOfStringInfo(vo.getWhetherToSupportStr()));
            infoList.add(getNotNullOfStringInfo(vo.getBusinessModelName()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerLevelName()));
            data.add(infoList);
        }
        //合计
        JSONArray titleList = new JSONArray();
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add(productNum);
        titleList.add("");
        titleList.add(moneySubtotalUSD);
        titleList.add(moneySubtotalRMB);
        titleList.add(carryNum);
        titleList.add(carryDetailNum);
        titleList.add(lastNum);
        titleList.add(lastNumOfDetail);
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");

        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        data.add(titleList);
    }

    /**
     * 获取excel的title信息 统计2
     * @return excel的title信息
     */
    private JSONArray getTitleInfoOfTwoStatistics(){
        JSONArray titleList = new JSONArray();
        titleList.add("外销合同号");
        titleList.add("客户名称");
        titleList.add("客户编码");
        titleList.add("客户合同号");
        titleList.add("签约日期");
        titleList.add("产品编码");
        titleList.add("规格编码");
        titleList.add("中文名称");
        titleList.add("数量");
        titleList.add("单价");
        titleList.add("USD金额小计");
        titleList.add("RMB金额小计");
        titleList.add("出运计划数量");
        titleList.add("出运明细数量");
        titleList.add("计划剩余数量");
        titleList.add("明细剩余数量");
        titleList.add("出货状态");
        titleList.add("签约公司");
        titleList.add("币种");
        titleList.add("人民币汇率");
        titleList.add("美元汇率");
        titleList.add("价格术语");
        titleList.add("业务员");
        titleList.add("操作员");
        titleList.add("客户账期");

        titleList.add("产品中文描述");
        titleList.add("产品英文描述");
        titleList.add("预收款类型");
        titleList.add("是否报关");
        titleList.add("货柜型号");
        titleList.add("瓶底是否指定Logo");
        titleList.add("客户特殊要求");
        titleList.add("是否打托");
        titleList.add("业务模式");
        titleList.add("客户级别");
        return titleList;
    }

    /**
     * 处理外销统计2数据
     * @param statisticsList 外销统计2数据
     * @return
     */
    private List<ContractStatisticsTwoVo> getContractStatisticsTwoInfo(List<ContractStatisticsTwoRsp> statisticsList){
        List<ContractStatisticsTwoVo> voList = new ArrayList<>();
        for(ContractStatisticsTwoRsp statisticsRsp : statisticsList){
            //初始化回参对象
            ContractStatisticsTwoVo vo = new ContractStatisticsTwoVo();
            //赋值
            BeanUtils.copyProperties(statisticsRsp, vo);
            //签约日期
            vo.setSigningDate(DateUtils.format(statisticsRsp.getSigningDate()));
            //美金汇率
            BigDecimal usdRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getUsdRate())){
                usdRate = statisticsRsp.getUsdRate();
            }
            //单价
            BigDecimal unitPrice = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getUnitPrice())){
                unitPrice = statisticsRsp.getUnitPrice();
            }
            //数量
            BigDecimal productNum = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getProductNum())){
                productNum = statisticsRsp.getProductNum();
            }
            //USD金额小计
            vo.setMoneySubtotalUSD(unitPrice.multiply(usdRate).multiply(productNum));
            //rmb汇率
            BigDecimal rmbRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getRmbRate())){
                rmbRate = statisticsRsp.getRmbRate();
            }
            if("usd-001".equals(statisticsRsp.getCurrencyCode()) || "rmb-001".equals(statisticsRsp.getCurrencyCode())){
                //RMB金额小计
                vo.setMoneySubtotalRMB(unitPrice.multiply(rmbRate).multiply(productNum));
            }else {
                //RMB金额小计
                vo.setMoneySubtotalRMB(unitPrice.multiply(usdRate).multiply(rmbRate).multiply(productNum));
            }

            //调用接口查询该产品在出运计划中的数量
            int count = shipmentPlanService.getPlanProduct(statisticsRsp.getBillNo(), statisticsRsp.getProductCode(), statisticsRsp.getSpecificationCode());
            //出运计划数量
            BigDecimal carryNum = new BigDecimal(Integer.toString(count));
            vo.setCarryNum(carryNum);
            //出运明细数量
            CarryDetailInfoReq queryReq = new CarryDetailInfoReq();
            //产品编码
            queryReq.setProductCode(statisticsRsp.getProductCode());
            //规格编码
            queryReq.setSpecNo(statisticsRsp.getSpecificationCode());
            //销售合同号
            queryReq.setSaleContractNo(statisticsRsp.getBillNo());
            //查询已做出运明细数量
            BigDecimal carryDetailNum = carryDetailService.getUsedCarryDetailNum(queryReq);
            vo.setCarryDetailNum(carryDetailNum);
            //计划剩余数量
            BigDecimal lastNum = productNum.subtract(carryNum);
            vo.setLastNum(lastNum);
            //明细剩余数量
            BigDecimal lastNumOfDetail = productNum.subtract(carryDetailNum);
            vo.setLastNumOfDetail(lastNumOfDetail);
            //出货状态(明细剩余数量大于零:未发货,否则已发货完成)
            if(lastNumOfDetail.compareTo(BigDecimal.ZERO) > 0){
                vo.setCarryStatus("未发货");
            }else {
                vo.setCarryStatus("已发货完成");
            }
            //计划剩余金额 = 计划剩余数量*单价
            vo.setLastAmountOfPlan(lastNum.multiply(unitPrice));
            //明细剩余金额 = 明细剩余数量*单价
            vo.setLastAmountOfDetail(lastNumOfDetail.multiply(unitPrice));

            if(null != statisticsRsp.getIsDeclare()){
                //是否报关(0:否 1:是)
                vo.setIsDeclareStr(statisticsRsp.getIsDeclare() == 1 ? "是" : "否");
            }
            if(null != statisticsRsp.getWhetherToSupport()){
                //是否打托(0:否 1:是)
                vo.setWhetherToSupportStr(statisticsRsp.getWhetherToSupport() == 1 ? "是" : "否");
            }
            //1:不指定，2：指定光面，3：指定客户Logo，4：指定Rtco Logo
            Integer modeOfTrade = statisticsRsp.getModeOfTrade();
            switch (modeOfTrade){
                case 1:
                    vo.setModeOfTradeStr("不指定");
                    break;
                case 2:
                    vo.setModeOfTradeStr("指定光面");
                    break;
                case 3:
                    vo.setModeOfTradeStr("指定客户Logo");
                    break;
                case 4:
                    vo.setModeOfTradeStr("指定Rtco Logo");
                    break;
                default:
                    vo.setModeOfTradeStr("");
                    break;
            }


            voList.add(vo);
        }

        return voList;
    }

    /**
     * 统计3
     * @param req 查询条件
     * @return 统计3
     */
    public PageInfo<ContractStatisticsOneVo> getContractStatisticsThree(ContractStatisticsOneReq req){
        //调用接口查询
        List<ContractStatisticsOneRsp> statisticsList = exportContractService.getContractStatisticsOne(req);
        //初始化回参对象集合
        List<ContractStatisticsOneVo> voList = new ArrayList<>();
        PageInfo pageInfo = new PageInfo(statisticsList);
        if(CollectionUtils.isEmpty(statisticsList)){
            pageInfo.setList(voList);
            return pageInfo;
        }
        voList = getContractStatisticsThreeInfo(statisticsList);

        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 统计3 导出Excel
     * @param req 查询条件
     * @return 统计3 导出Excel
     */
    public JSONObject getContractStatisticsThreeInfo(ContractStatisticsOneReq req){
        //调用接口查询
        List<ContractStatisticsOneRsp> statisticsList = exportContractService.getContractStatisticsOne(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleInfoOfThreeStatistics();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(statisticsList)){
            obj.put("data", data);
            return obj;
        }
        List<ContractStatisticsOneVo> voList = getContractStatisticsThreeInfo(statisticsList);

        //封装数据
        getThreeStatisticsInfo(data, voList);

        obj.put("data", data);
        return obj;
    }

    /**
     * 封装数据
     * @param data 封装后数据
     * @param voList 原始数据
     */
    private void getThreeStatisticsInfo(JSONArray data, List<ContractStatisticsOneVo> voList){
        BigDecimal amountUSD = new BigDecimal("0");
        BigDecimal amountRMB = new BigDecimal("0");
        BigDecimal totalContractAmount = new BigDecimal("0");
        for(ContractStatisticsOneVo vo : voList){
            JSONArray infoList = new JSONArray();
            infoList.add(getNotNullOfStringInfo(vo.getBillNo()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerName()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerSource()));
            infoList.add(getNotNullOfStringInfo(vo.getPriceTermsName()));
            infoList.add(vo.getSigningDate() == null ? "" : vo.getSigningDate());
            infoList.add(getNotNullOfStringInfo(vo.getCheckStatusStr()));
            infoList.add(getNotNullOfStringInfo(vo.getStatusStr()));
            infoList.add(getNotNullOfStringInfo(vo.getPaymentTypeName()));
            infoList.add(getNotNullOfStringInfo(vo.getModeOfTransport()));
            infoList.add(getNotNullOfStringInfo(vo.getCurrency()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalContractAmount()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalContractAmountUSD()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalContractAmountRMB()));
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanName()));
            infoList.add(getNotNullOfStringInfo(vo.getIsPurchase()));
            infoList.add(getNotNullOfStringInfo(vo.getSigningCompanyName()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerContactNo()));



            infoList.add(getNotNullOfBigDecimalInfo(vo.getRmbRate()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUsdRate()));
            infoList.add(vo.getCarryTime() == null ? "" : vo.getCarryTime());
            infoList.add(getNotNullOfStringInfo(vo.getOperator()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerAccountingPeriod()));
            infoList.add(getNotNullOfStringInfo(vo.getMemo()));


            if(StringUtil.isNotEmpty(vo.getTotalContractAmount())){
                totalContractAmount = totalContractAmount.add(vo.getTotalContractAmount());
            }
            if(StringUtil.isNotEmpty(vo.getTotalContractAmountUSD())){
                amountUSD = amountUSD.add(vo.getTotalContractAmountUSD());
            }
            if(StringUtil.isNotEmpty(vo.getTotalContractAmountRMB())){
                amountRMB = amountRMB.add(vo.getTotalContractAmountRMB());
            }


            data.add(infoList);
        }
        JSONArray titleList = new JSONArray();
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add(totalContractAmount);
        titleList.add(amountUSD);
        titleList.add(amountRMB);
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");
        titleList.add("");

        data.add(titleList);
    }

    /**
     * 获取excel的title信息 统计3
     * @return excel的title信息
     */
    private JSONArray getTitleInfoOfThreeStatistics(){
        JSONArray titleList = new JSONArray();
        titleList.add("外销合同编号");
        titleList.add("客户名称");
        titleList.add("客户来源");
        titleList.add("价格术语");
        titleList.add("签约日期");
        titleList.add("审批状态");
        titleList.add("执行状态");
        titleList.add("付款类型");
        titleList.add("运输方式");
        titleList.add("币种");
        titleList.add("合同总额");
        titleList.add("USD合同总额");
        titleList.add("RMB合同总额");
        titleList.add("业务员");
        titleList.add("是否已做采购");
        titleList.add("签约公司");
        titleList.add("客户合同号");

        titleList.add("人民币汇率");
        titleList.add("美元汇率");
        titleList.add("出运日期");
        titleList.add("操作员");
        titleList.add("客户账期");
        titleList.add("备注");

        return titleList;
    }

    private List<ContractStatisticsOneVo> getContractStatisticsThreeInfo(List<ContractStatisticsOneRsp> statisticsList){
        //初始化回参对象集合
        List<ContractStatisticsOneVo> voList = new ArrayList<>();
        //查询是否成交
        for(ContractStatisticsOneRsp statisticsRsp : statisticsList){
            //初始化回参对象
            ContractStatisticsOneVo vo = new ContractStatisticsOneVo();
            //赋值
            BeanUtils.copyProperties(statisticsRsp, vo);
            //签约日期
            vo.setSigningDate(DateUtils.format(statisticsRsp.getSigningDate()));
            //出运日期
            vo.setCarryTime(DateUtils.format(statisticsRsp.getCarryTime()));
            //合同总额
            BigDecimal totalContractAmount = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getTotalContractAmount())){
                totalContractAmount = statisticsRsp.getTotalContractAmount();
            }
            //美金汇率
            BigDecimal usdRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getUsdRate())){
                usdRate = statisticsRsp.getUsdRate();
            }
            //rmb汇率
            BigDecimal rmbRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(statisticsRsp.getRmbRate())){
                rmbRate = statisticsRsp.getRmbRate();
            }
            if (statisticsRsp.getCurrency().equals("人民币") || statisticsRsp.getCurrency().equals("RMB")) {
                if(usdRate.compareTo(BigDecimal.valueOf(1)) == 1){
                    vo.setTotalContractAmountUSD(totalContractAmount.divide(usdRate, 2, BigDecimal.ROUND_HALF_UP));
                }else{
                    vo.setTotalContractAmountUSD(totalContractAmount.multiply(usdRate).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
                }
                vo.setTotalContractAmountRMB(totalContractAmount);
            }else{
                vo.setTotalContractAmountUSD((totalContractAmount.multiply(usdRate)).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
                vo.setTotalContractAmountRMB(totalContractAmount.multiply(usdRate).multiply(rmbRate).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
            }
            //是否已做采购
            if(StringUtils.isEmpty(statisticsRsp.getPurchaseSalesContractNo())){
                vo.setIsPurchase("否");
            }else {
                vo.setIsPurchase("是");
            }
            Integer status = statisticsRsp.getStatus();
            switch (status){
                case 1:
                    vo.setCheckStatusStr("草稿");
                    vo.setStatusStr("未执行");
                    break;
                case 2:
                    vo.setCheckStatusStr("待批");
                    vo.setStatusStr("待执行");
                    break;
                case 3:
                    vo.setCheckStatusStr("已批");
                    vo.setStatusStr("在执行");
                    break;
                case 4:
                    vo.setCheckStatusStr("已完成");
                    vo.setStatusStr("已完成");
                    break;
                default:
                    vo.setCheckStatusStr("终止");
                    vo.setStatusStr("终止");
                    break;
            }

            voList.add(vo);
        }

        return voList;
    }


    /**
     * 根据参数返回拼接之后的logo的url
     * @return
     */
   public CompanyLogo getImgLogoUrl(Integer id){
       CompanyLogo companyLogo=exportContractService.getImgLogoUrl(id);
       return companyLogo;
   }


    /**
     * 查询外销实体
     * @param id
     * @return
     */
    public ExportContractEntity queryById(Integer id) {
        return exportContractService.queryById(id);
    }

    /**
     * 获取本月外销合同数量
     * @param name 操作员
     * @param code 操作员编码
     * @return 本月外销合同数量
     */
    public long getExportBillNoCount(String name, String code){
        //初始化查询对象
        StatisticsInfoReq infoReq = new StatisticsInfoReq();
        infoReq.setOperator(name);
        infoReq.setOperationCode(code);
        infoReq.setCreateDateStart(DateUtils.format(DateUtils.getStartTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        infoReq.setCreateDateEnd(DateUtils.format(DateUtils.getEndTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        //查询结果
        return exportContractService.getExportBillNoCount(infoReq);
    }

    /**
     * 获取本月外销合同总额USD
     * @param name 操作员
     * @param code 操作员编码
     * @return 本月外销合同总额USD
     */
    public BigDecimal getTotalContractAmount(String name, String code){
        //初始化查询对象
        StatisticsInfoReq infoReq = new StatisticsInfoReq();
        infoReq.setOperator(name);
        infoReq.setOperationCode(code);
        infoReq.setCreateDateStart(DateUtils.format(DateUtils.getStartTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        infoReq.setCreateDateEnd(DateUtils.format(DateUtils.getEndTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        //查询结果
        List<ExportContractEntity> contractList = exportContractService.getExportInfo(infoReq);
        if(CollectionUtils.isEmpty(contractList)){
            return new BigDecimal("0.00");
        }
        //本月外销合同总额USD
        BigDecimal num = new BigDecimal("0");
        for(ExportContractEntity contract : contractList){
            //美金汇率
            BigDecimal usdRate = new BigDecimal("0");
            if(StringUtil.isNotEmpty(contract.getUsdRate())){
                usdRate = contract.getUsdRate();
            }
            //合同总额
            BigDecimal totalContractAmount = new BigDecimal("0");
            if(StringUtil.isNotEmpty(contract.getTotalContractAmount())){
                totalContractAmount = contract.getTotalContractAmount();
            }
            BigDecimal usdAmount = usdRate.multiply(totalContractAmount);

            num = num.add(usdAmount);
        }
        return num;
    }

    /**
     * 获取本月报价成交率
     * @param name 操作员
     * @param code 操作员编码
     * @return 本月报价成交率
     */
    public BigDecimal getOfferTurnoverRate(String name, String code){
        //初始化查询对象
        StatisticsInfoReq infoReq = new StatisticsInfoReq();
        infoReq.setOperator(name);
        infoReq.setOperationCode(code);
        infoReq.setCreateDateStart(DateUtils.format(DateUtils.getStartTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        infoReq.setCreateDateEnd(DateUtils.format(DateUtils.getEndTimeOfTheMonth(), DateUtils.DATE_PATTERN));
        //查询结果
        StatisticsOfferBillNoRsp billNoInfo = exportContractService.getStatisticsOfferBillNo(infoReq);
        BigDecimal turnoverRate = new BigDecimal("0.00");
        if(null == billNoInfo){
            return turnoverRate;
        }
        //总单数
        BigDecimal sumNo = new BigDecimal(Integer.toString(billNoInfo.getSumNo()));
        //本月成交单数
        BigDecimal sumChild = new BigDecimal(Integer.toString(billNoInfo.getSumChild()));
        if(!StringUtil.isNotEmpty(sumChild)){
            return turnoverRate;
        }

        turnoverRate =  sumNo.divide(sumChild, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));

        return turnoverRate;
    }

    /**
     * 控制台-获取外销信息
     * @param name 当前用户
     * @param code 当前用户编码
     * @return 外销信息
     */
    public PageInfo<StatisticsExportInfoVo> getStatisticsExportInfoByPage(String name, String code){
        //初始化查询对象
        StatisticsInfoReq infoReq = new StatisticsInfoReq();
        infoReq.setOperator(name);
        infoReq.setOperationCode(code);
        //查询结果
        List<StatisticsExportInfoRsp> exportInfo = exportContractService.getStatisticsExportInfo(infoReq);
        PageInfo pageInfo = new PageInfo(exportInfo);
        List<StatisticsExportInfoVo> voList = getStatisticsExportInfo(exportInfo);
        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 外销合同交期详情导出Excel
     *
     * @param name 用户名称
     * @param code 用户编码
     * @return 导出Excel的json数据
     */
    public JSONObject getStatisticsExportInfo(String name, String code) {
        //初始化查询对象
        StatisticsInfoReq infoReq = new StatisticsInfoReq();
        infoReq.setOperator(name);
        infoReq.setOperationCode(code);
        //查询结果
        List<StatisticsExportInfoRsp> exportInfo = exportContractService.getStatisticsExportInfo(infoReq);
        //处理查询的数据信息
        List<StatisticsExportInfoVo> voList = getStatisticsExportInfo(exportInfo);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getStatisticsExportTitle();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if (CollectionUtils.isEmpty(voList)) {
            obj.put("data", data);
            return obj;
        }
        //封装导出Excel数据
        setStatisticsExportInfo(data, voList);

        obj.put("data", data);
        return obj;
    }

    /**
     * 封装导出Excel数据
     *
     * @param data   导出的json数据
     * @param voList 源数据
     */
    private void setStatisticsExportInfo(JSONArray data, List<StatisticsExportInfoVo> voList) {
        for (StatisticsExportInfoVo vo : voList) {
            JSONArray info = new JSONArray();
            info.add(getNotNullOfStringInfo(vo.getBillNo()));
            info.add(getNotNullOfStringInfo(vo.getPurchaseNo()));
            info.add(getNotNullOfStringInfo(vo.getProductCode()));
            info.add(getNotNullOfStringInfo(vo.getDeliveryDate()));
            info.add(getNotNullOfStringInfo(vo.getFeedbackDeliveryDate()));
            info.add(getNotNullOfStringInfo(vo.getActualDeliveryDate()));
            info.add(getNotNullOfBigDecimalInfo(vo.getProductNum()));
            info.add(getNotNullOfStringInfo(vo.getMemo()));

            data.add(info);
        }
    }

    /**
     * 获取控制台外销合同交期详情导出excel的title信息
     *
     * @return 控制台外销合同交期详情导出excel的title信息
     */
    private JSONArray getStatisticsExportTitle() {
        JSONArray obj = new JSONArray();
        obj.add("外销合同信息");
        obj.add("采购单号");
        obj.add("产品编码");
        obj.add("采购交期");
        obj.add("供应商反馈交期");
        obj.add("实际交期");
        obj.add("数量");
        obj.add("备注");
        return obj;
    }

    /**
     * 处理外销采购结果数据
     *
     * @param exportInfo 外销采购数据
     * @return 处理后的外销采购结果数据
     */
    private List<StatisticsExportInfoVo> getStatisticsExportInfo(List<StatisticsExportInfoRsp> exportInfo) {
        //初始化回参对象集合
        List<StatisticsExportInfoVo> voList = new ArrayList<>();
        if (CollectionUtils.isEmpty(exportInfo)) {
            return voList;
        }
        for (StatisticsExportInfoRsp export : exportInfo) {
            StatisticsExportInfoVo vo = new StatisticsExportInfoVo();
            //赋值
            BeanUtils.copyProperties(export, vo);
            //要求交货日期
            vo.setDeliveryDate(DateUtils.format(export.getDeliveryDate()));
            //供应商反馈交期
            vo.setFeedbackDeliveryDate(DateUtils.format(export.getFeedbackDeliveryDate()));
            //实际交期
            vo.setActualDeliveryDate(DateUtils.format(export.getActualDeliveryDate()));

            voList.add(vo);
        }
        return voList;
    }

    /**
     * 修改该条记录，总金额转英文
     * @return
     */
    public R update(Integer id){
        //得到外销实体信息
        ExportContractEntity exportContractEntity=exportContractService.queryById(id);
        BigDecimal totalContractAmount=exportContractEntity.getTotalContractAmount();
        //总金额转换成double
        Double totalContractAmountDouble=totalContractAmount.doubleValue();
        DecimalFormat df=new DecimalFormat("#.00");
        //总金额转换成double
        String totalContractAmountEnglish=numberParseToEnglish(df.format(totalContractAmountDouble));
        //设置转换之后的英文
        exportContractEntity.setTotalContractAmountEnglish(totalContractAmountEnglish);
        //修改
        int num=exportContractService.update(exportContractEntity);
        if (num==1){
            return R.build(ResultStatusEnum.SUCCESS);
        }
        return R.build(ResultStatusEnum.DATA_ERROR);
    }

    /**
     * 将数值转换成英文，小数点前9位，小数点后2位
     * @param money
     * @return
     */
    public static String numberParseToEnglish(String money){
        //个位
        String[] smallNumbers = new String[]{"ZERO",  "ONE",  "TWO",  "THREE",  "FOUR",  "FIVE",
                "SIX",  "SEVEN",  "EIGHT",  "NINE",  "TEN",
                "ELEVEN",  "TWELVE",  "THIRTEEN",  "FOURTEEN",  "FIFTEEN",
                "SIXTEEN",  "SEVENTEEN",  "EIGHTEEN",  "NINETEEN"};
        //十位
        String[] tensNumbers = new String[]{ "",  "",  "TWENTY",  "THIRTY",  "FORTY",  "FIFTY",  "SIXTY",  "SEVENTY",  "EIGHTY", "NINETY"};
        //百位
        String[] scaleNumers = new String[]{"", "THOUSAND", "MILLION", "BILLION" };
        String end = "ONLY";

        double dMoney = Double.parseDouble(money);
        String[] arrMoney = money.split("\\.");
        //小数点前
        int decimals1 = 0;
        //小数点后
        int decimals2 = 0;
        //纯小数
        if(dMoney < 1){
            decimals1 = 0;
        }else{
            decimals1 = Integer.parseInt(arrMoney[0]);
        }
        decimals2 = Integer.parseInt(arrMoney[1]);
        //初始化显示英文为ZERO
        String combined1 = smallNumbers[0];
        String combined2 = smallNumbers[0];
        //小数点之前的数不等于0
        if(decimals1 != 0){

            int[] digitGroups = new int[]{0,0,0,0};
//            将金额拆分成4段，每段放3位数，即：XXX,XXX,XXX,XXX。最大仅支持到Billion，
            for(int i=0;i<4;i++){
                digitGroups[i] = decimals1%1000;
                decimals1 = decimals1/1000;
            }

            System.out.println("digitGroups"+ Arrays.toString(digitGroups));

            String[] groupText = new String[]{"","","",""};
            //处理每段的金额转英文，百位+十位+个位
            for(int i=0;i<4;i++){
                int hundreds = digitGroups[i]/100;
                int tensUnits = digitGroups[i]%100;

                //百位
                if(hundreds!=0){
                    groupText[i] = groupText[i] + smallNumbers[hundreds] + " HUNDRED ";
                    if(tensUnits!=0){
                        groupText[i] = groupText[i] + "AND ";
                    }
                }

                if (tensUnits>=20){//两位数大于等于20
                    //十位和个位
                    int tens = tensUnits/10;
                    int units = tensUnits%10;
                    groupText[i] = groupText[i] + tensNumbers[tens];
                    if(units!=0){
                        groupText[i] = groupText[i] + "-" + smallNumbers[units];
                    }
                }else if (tensUnits>0){//两位数小于20的情况大于0的情况
                    groupText[i] = groupText[i] + smallNumbers[tensUnits] ;
                }


            }
            //金额的个十百位赋值到combined
            combined1 = groupText[0];
            //将金额排除个十百位以外，余下的3段英文数字，加上千位分隔符英文单词，Thousand/Million/Billion
            for(int i=1;i<4;i++){
                if (digitGroups[i]!=0){
                    String prefix = groupText[i] + " " + scaleNumers[i];  //A:组合Thousand 和Billion
                    if (combined1.length()!=0){ //如果金额的百位+十位+个位非0,则在后面加上空格
                        prefix = prefix+ " ";
                    }
                    combined1 = prefix + combined1; //再连接 A+B

                }
            }
        }

        if(decimals2!=0){
            //十位和个位
            int tens  = decimals2/10;
            int units = decimals2%10;

            if(decimals2 >=20){
                combined2 = "AND CENTS " + tensNumbers[tens];
                if(units!=0){
                    combined2 = combined2 + "-" + smallNumbers[units];
                }
            }else if(decimals2 > 1){//19到2之间
                combined2 = "AND CENTS " + smallNumbers[decimals2];
            }else{
                combined2 = "AND CENT " + smallNumbers[decimals2];
            }
        }

        if(!combined1.equals("ZERO")){
            if(!combined2.equals("ZERO")){
                return combined1 + " " + combined2 + " " + end;
            }else{
                return combined1+ " " + end;
            }
        }else if(!combined2.equals("ZERO")){
            return combined2 + " " + end;
        }else{
            return "ZERO";
        }
    }


    /**
     * 客户订单第一次记录 统计
     * @param req
     * @return
     */
    public PageInfo<CustomerInformationRecordRes> getFirstCustomerInfoListByPage(CustomerInformationRecordReq req) {
        List<CustomerInformationRecordRes> customerInformationRecordResList=exportContractService.getFirstCustomerInfoList(req);
        for (CustomerInformationRecordRes p:customerInformationRecordResList){
            p.setSigningDateStr(DateUtils.format(p.getSigningDate(),DateUtils.DATE_PATTERN));
        }
        PageInfo<CustomerInformationRecordRes> pageInfo=new PageInfo<>(customerInformationRecordResList);
        pageInfo.setList(customerInformationRecordResList);
        return pageInfo;
    }
    /**
     * 客户订单第一次记录-导出
     * @param req
     * @return
     */
    public JSONObject getFirstCustomerInfoExport(CustomerInformationRecordReq req){
        List<CustomerInformationRecordRes> customerInformationRecordResList=exportContractService.getFirstCustomerInfoList(req);
        for (CustomerInformationRecordRes p:customerInformationRecordResList){
            p.setSigningDateStr(DateUtils.format(p.getSigningDate(),DateUtils.DATE_PATTERN));
        }

        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleInfo();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(customerInformationRecordResList)){
            obj.put("data", data);
            return obj;
        }
        excelInfoExport(data,customerInformationRecordResList);
        obj.put("data", data);
        return obj;
    }
    public JSONArray getTitleInfo(){
        JSONArray obj=new JSONArray();
        obj.add("外销合同号");
        obj.add("第一次签约日期");
        obj.add("客户编码");
        obj.add("客户名称");
        obj.add("简称");
        obj.add("客户类型");
        obj.add("业务员");
        obj.add("客户地址");
        obj.add("等级");
        obj.add("账期");
        obj.add("信用额度");
        obj.add("国家");
        obj.add("客户来源");
        return obj;
    }
    public void excelInfoExport(JSONArray data,List<CustomerInformationRecordRes> list) {
        for (CustomerInformationRecordRes vo : list) {
            JSONArray infoList = new JSONArray();
            infoList.add(getNotNullOfStringInfo(vo.getContractNo()));
            infoList.add(getNotNullOfStringInfo(vo.getSigningDateStr()));
            infoList.add(getNotNullOfStringInfo(vo.getCode()));
            infoList.add(getNotNullOfStringInfo(vo.getName()));
            infoList.add(getNotNullOfStringInfo(vo.getAbbreviation()));
            infoList.add(getNotNullOfStringInfo(vo.getTypeName()));
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanName()));
            infoList.add(getNotNullOfStringInfo(vo.getAddress()));
            infoList.add(getNotNullOfStringInfo(vo.getLevelName()));
            infoList.add(getNotNullOfStringInfo(vo.getAccountPeriod()));
            infoList.add(getNotNullOfStringInfo(vo.getCreditLine()));
            infoList.add(getNotNullOfStringInfo(vo.getCountry()));
            infoList.add(getNotNullOfStringInfo(vo.getSourceOfCustomers()));
            data.add(infoList);
        }
    }


    /**
     * 外销产品交期一览表统计-集合
     * @param req
     * @return
     */
    private List<DeliveryDateInfoRes> getDeliveryDateInfoList(DeliveryDateInfoReq req){
        List<DeliveryDateInfoRes> deliveryDateInfoResList=exportContractService.getDeliveryDateInfoList(req);
        for (DeliveryDateInfoRes p: deliveryDateInfoResList) {
            p.setContractDeliveryDateStr(DateUtils.format(p.getContractDeliveryDate(),DateUtils.DATE_PATTERN));
            p.setContractSigningDateStr(DateUtils.format(p.getContractSigningDate(),DateUtils.DATE_PATTERN));
            p.setPurchaseDeliveryDateStr(DateUtils.format(p.getPurchaseDeliveryDate(),DateUtils.DATE_PATTERN));
            p.setPurchaseSigningDateStr(DateUtils.format(p.getPurchaseSigningDate(),DateUtils.DATE_PATTERN));
            p.setFeedbackDeliveryDateStr(DateUtils.format(p.getFeedbackDeliveryDate(),DateUtils.DATE_PATTERN));
            p.setActualDeliveryDateStr(DateUtils.format(p.getActualDeliveryDate(),DateUtils.DATE_PATTERN));
            if (p.getCarryNum()==null){
                p.setCarryNum(new BigDecimal(0));
            }
            p.setUnCarryNum(p.getProductNum().subtract(p.getCarryNum()));
        }
        return deliveryDateInfoResList;
    }
    /**
     * 外销产品交期一览表统计-分页
     * @param req
     * @return
     */
    public PageInfo<DeliveryDateInfoRes> getDeliveryDateInfoListByPage(DeliveryDateInfoReq req){
        List<DeliveryDateInfoRes> getDeliveryDateInfoList=getDeliveryDateInfoList(req);
        PageInfo<DeliveryDateInfoRes> pageInfo=new PageInfo<>(getDeliveryDateInfoList);
        return pageInfo;
    }
    /**
     * 外销产品交期一览表统计-导出
     * @param req
     * @return
     */
    public JSONObject getDeliveryDateInfoListExport(DeliveryDateInfoReq req){
        List<DeliveryDateInfoRes> getDeliveryDateInfoList=getDeliveryDateInfoList(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleDeliveryDateInfo();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(getDeliveryDateInfoList)){
            obj.put("data", data);
            return obj;
        }
        excelDeliveryDateInfoExport(data,getDeliveryDateInfoList);
        obj.put("data", data);
        return obj;
    }
    private JSONArray getTitleDeliveryDateInfo(){
        JSONArray obj=new JSONArray();
        obj.add("外销业务员");
        obj.add("采购操作员");
        obj.add("外销合同签约日期");
        obj.add("外销合同号");
        obj.add("采购单号");
        obj.add("采购合同签约日期");
        obj.add("产品编码");
        obj.add("规格编码");
        obj.add("外销要求交期");
        obj.add("中文描述");
        obj.add("英文描述");
        obj.add("采购回馈交期");
        obj.add("产品数量");
        obj.add("供应商反馈交期");
        obj.add("实际交期");

        obj.add("已出货数量");
        obj.add("未出货数量");
        obj.add("出货目的地");
        obj.add("箱型40HQ`20GP`LCL`(空运 or 海运)");
        obj.add("本月计划数量");
        obj.add("需求提出日期");
        obj.add("供出商实际出货日期");
        return obj;
    }
    private void excelDeliveryDateInfoExport(JSONArray data,List<DeliveryDateInfoRes> list){
        for (DeliveryDateInfoRes vo : list) {
            JSONArray infoList = new JSONArray();
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanName()));
            infoList.add(getNotNullOfStringInfo(vo.getOperatorName()));
            infoList.add(getNotNullOfStringInfo(vo.getContractSigningDateStr()));
            infoList.add(getNotNullOfStringInfo(vo.getContractNo()));
            infoList.add(getNotNullOfStringInfo(vo.getPurchaseOrderNo()));
            infoList.add(getNotNullOfStringInfo(vo.getPurchaseSigningDateStr()));
            infoList.add(getNotNullOfStringInfo(vo.getProductCode()));
            infoList.add(getNotNullOfStringInfo(vo.getSpecCode()));
            infoList.add(getNotNullOfStringInfo(vo.getContractDeliveryDateStr()));
            infoList.add(getNotNullOfStringInfo(vo.getChineseDesc()));
            infoList.add(getNotNullOfStringInfo(vo.getEnglishDesc()));
            infoList.add(getNotNullOfStringInfo(vo.getPurchaseDeliveryDateStr()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getProductNum()));
            infoList.add(getNotNullOfStringInfo(vo.getFeedbackDeliveryDateStr()));
            infoList.add(getNotNullOfStringInfo(vo.getActualDeliveryDateStr()));

            infoList.add(getNotNullOfBigDecimalInfo(vo.getCarryNum()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getUnCarryNum()));
            infoList.add(getNotNullOfStringInfo(vo.getDestinationName()));
            infoList.add(getNotNullOfStringInfo(vo.getContainerType()));
            infoList.add("");
            infoList.add("");
            infoList.add("");
            infoList.add("");
            data.add(infoList);
        }


    }

    /**
     * 客户订单总表
     * @param req 查询参数
     * @return 客户订单总表
     */
    public PageInfo<ContractCustomerInfoVo> getContractCustomerInfoByPage(ContractCustomerInfoReq req){
        //获取客户订单信息
        List<ContractCustomerInfoRsp> contractCustomerInfo = exportContractService.getContractCustomerInfo(req);
        PageInfo pageInfo = new PageInfo(contractCustomerInfo);
        pageInfo.setList(getContractCustomerInfo(contractCustomerInfo));
        return pageInfo;
    }

    /**
     * 数据处理
     * @param contractCustomerInfo 外销客户信息
     * @return 处理后的外销客户信息
     */
    private List<ContractCustomerInfoVo> getContractCustomerInfo(List<ContractCustomerInfoRsp> contractCustomerInfo){
        //初始化回参对象集合
        List<ContractCustomerInfoVo> voList = new ArrayList<>();
        if(CollectionUtils.isEmpty(contractCustomerInfo)){
            return voList;
        }
        for(ContractCustomerInfoRsp info : contractCustomerInfo){
            ContractCustomerInfoVo vo = new ContractCustomerInfoVo();
            //赋值
            BeanUtils.copyProperties(info, vo);
            //日期处理
            vo.setCreateDate(DateUtils.format(info.getCreateDate()));

            voList.add(vo);
        }

        return voList;
    }

    /**
     * 客户订单总表-导出Excel
     * @param req 查询条件
     * @return 客户订单总表
     */
    public JSONObject getContractCustomerInfo(ContractCustomerInfoReq req){
        //获取客户订单信息
        List<ContractCustomerInfoRsp> contractCustomerInfo = exportContractService.getContractCustomerInfo(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleInfoOfContractCustomer();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(contractCustomerInfo)){
            obj.put("data", data);
            return obj;
        }
        List<ContractCustomerInfoVo> voList = getContractCustomerInfo(contractCustomerInfo);

        //封装数据
        getContractCustomerInfo(data, voList);

        obj.put("data", data);
        return obj;
    }

    /**
     * 获取excel的title信息
     * 客户订单信息
     * @return excel的title信息
     */
    private JSONArray getTitleInfoOfContractCustomer(){
        JSONArray titleList = new JSONArray();
        titleList.add("客户编码");
        titleList.add("客户名称");
        titleList.add("客户来源");
        titleList.add("客户创建日期");
        titleList.add("客户业务员");
        titleList.add("外销业务员");
        titleList.add("合同总额");
        titleList.add("合同总额USD");
        titleList.add("合同总额RMB");

        return titleList;
    }

    /**
     * 封装数据
     * @param data 封装后数据
     * @param voList 原始数据
     */
    private void getContractCustomerInfo(JSONArray data, List<ContractCustomerInfoVo> voList){
        for(ContractCustomerInfoVo vo : voList){
            JSONArray infoList = new JSONArray();
            infoList.add(getNotNullOfStringInfo(vo.getCustomerCode()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerName()));
            infoList.add(getNotNullOfStringInfo(vo.getSourceOfCustomers()));
            infoList.add(vo.getCreateDate() == null ? "" : vo.getCreateDate());
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanNameCustomer()));
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanNameContract()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalContractAmount()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalAmountUsd()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getTotalAmountRmb()));

            data.add(infoList);
        }
    }


    /**
     * 外销费用统计--集合
     * @return
     */
    private List<ExportExpensesRes> getExportExpensesList(ExportExpensesReq req){
        List<ExportExpensesRes> list = exportContractService.getExportExpensesList(req);
        for (ExportExpensesRes p:list){
            p.setSigningDateStr(DateUtils.format(p.getSigningDate(),DateUtils.DATE_PATTERN));
            if (StringUtils.isNotEmpty(p.getStatus())){
                switch (p.getStatus()){
                    case "1":
                        p.setStatus("草稿箱");
                        break;
                    case "2":
                        p.setStatus("待批箱");
                        break;
                    case "3":
                        p.setStatus("已批箱");
                        break;
                    case "4":
                        p.setStatus("完成箱");
                        break;
                    case "5":
                        p.setStatus("垃圾箱");
                        break;
                }
            }



            String currency = p.getCurrency();
            //美金汇率
            BigDecimal usdRate = p.getUsdRate();
            //rmb汇率
            BigDecimal rmbRate = p.getRmbRate();

            BigDecimal amount = p.getAmount();

            if (rmbRate!=null && usdRate!=null){
                if (currency.equals("人民币") || currency.equals("RMB")) {
                    if(usdRate.compareTo(BigDecimal.valueOf(1)) == 1){
                        p.setAmountUsd(amount.divide(usdRate, 2, BigDecimal.ROUND_HALF_UP));
                    }else{
                        p.setAmountUsd(amount.multiply(usdRate).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
                    }
                    p.setAmountRmb(amount);
                }else{
                    p.setAmountUsd((amount.multiply(usdRate)).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
                    p.setAmountRmb(amount.multiply(usdRate).multiply(rmbRate).divide(BigDecimal.valueOf(1), 2, BigDecimal.ROUND_HALF_UP));
                }
            }




        }
        return list;
    }
    /**
     * 外销费用统计--分页
     */
    public PageInfo<ExportExpensesRes> getExportExpensesByPage(ExportExpensesReq req){
        List<ExportExpensesRes> contractCustomerInfo = getExportExpensesList(req);
        PageInfo pageInfo = new PageInfo(contractCustomerInfo);
        return pageInfo;
    }

    /**
     * 外销费用统计-导出Excel
     */
    public JSONObject getExportExpensesExport(ExportExpensesReq req){
        List<ExportExpensesRes> exportExpensesList = getExportExpensesList(req);
        JSONObject obj = new JSONObject();
        //获取excel的title信息
        JSONArray titleList = getTitleExportExpenses();
        JSONArray data = new JSONArray();
        data.add(titleList);
        if(CollectionUtils.isEmpty(exportExpensesList)){
            obj.put("data", data);
            return obj;
        }
        //封装数据
        getExportExpenses(data, exportExpensesList);

        obj.put("data", data);
        return obj;
    }

    /**
     * 获取excel的title信息
     * 客户订单信息
     * @return excel的title信息
     */
    private JSONArray getTitleExportExpenses(){
        JSONArray titleList = new JSONArray();
        titleList.add("序号");
        titleList.add("单据类型");
        titleList.add("外销合同号");
        titleList.add("业务员");
        titleList.add("费用类型");

        titleList.add("币种");
        titleList.add("费用金额");
        titleList.add("费用金额(USD)");
        titleList.add("费用金额(RMB)");


        titleList.add("签约日期");
        titleList.add("客户名称");
        titleList.add("费用描述");
        return titleList;
    }

    /**
     * 封装数据
     * @param data 封装后数据
     * @param voList 原始数据
     */
    private void getExportExpenses(JSONArray data, List<ExportExpensesRes> voList){
        //费用金额
        BigDecimal amount = new BigDecimal("0");
        //费用金额(USD)
        BigDecimal amountUsd = new BigDecimal("0");
        //费用金额(RMB)
        BigDecimal amountRmb = new BigDecimal("0");

        Integer i=0;
        for(ExportExpensesRes vo : voList){
            JSONArray infoList = new JSONArray();
            infoList.add(++i);

            infoList.add(getNotNullOfStringInfo(vo.getStatus()));
            infoList.add(getNotNullOfStringInfo(vo.getSaleContractNo()));
            infoList.add(getNotNullOfStringInfo(vo.getSalesmanName()));
            infoList.add(getNotNullOfStringInfo(vo.getCostTypeName()));

            infoList.add(getNotNullOfStringInfo(vo.getCurrency()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getAmount()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getAmountUsd()));
            infoList.add(getNotNullOfBigDecimalInfo(vo.getAmountRmb()));

            infoList.add(getNotNullOfStringInfo(vo.getSigningDateStr()));
            infoList.add(getNotNullOfStringInfo(vo.getCustomerName()));
            infoList.add(getNotNullOfStringInfo(vo.getCostDesc()));
            if(StringUtil.isNotEmpty(vo.getAmount())){
                amount = amount.add(vo.getAmount());
            }
            if(StringUtil.isNotEmpty(vo.getAmountUsd())){
                amountUsd = amountUsd.add(vo.getAmountUsd());
            }
            if(StringUtil.isNotEmpty(vo.getAmountRmb())){
                amountRmb = amountRmb.add(vo.getAmountRmb());
            }

            data.add(infoList);
        }

        //合计
        JSONArray infoList = new JSONArray();
        infoList.add("合计");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");
        infoList.add("");

        infoList.add(amount);
        infoList.add(amountUsd);
        infoList.add(amountRmb);

        infoList.add("");
        infoList.add("");
        infoList.add("");

        data.add(infoList);

    }

    /**
     * 通过采购单号获取已做计划数量
     *
     * @param purchaseNo 采购单号
     * @return 已做计划数量
     */
    public int getPlanCountByPurchaseNo(String purchaseNo) {
        if (StringUtils.isEmpty(purchaseNo)) {
            return 0;
        }
        return exportContractProductService.getPlanCountByPurchaseNo(purchaseNo);
    }

    /**
     * 外销产品、配件终止、取消终止
     * @param req 操作入参
     */
    public void updateProductOrPartsStatus(UpdateProductOrPartsStatusReq req) {
        if (null == req.getId() || null == req.getStatus() || null == req.getType()) {
            return;
        }
        if (req.getType() == 1) {
            //产品修改
            ExportContractProductEntity exportContractProduct = new ExportContractProductEntity();
            exportContractProduct.setId(req.getId());
            exportContractProduct.setStatus(req.getStatus());
            exportContractProductService.update(exportContractProduct);
            //对应配件也进行终止、取消终止
            ExportContractProductPartsEntity partsReq = new ExportContractProductPartsEntity();
            //产品id
            partsReq.setDetailId(req.getId());
            //数据有效
            partsReq.setValid(DataIsValidEnum.VALID.getId());
            List<ExportContractProductPartsEntity> partsList = exportContractProductPartsService.queryAll(partsReq);
            if(CollectionUtils.isEmpty(partsList)){
                return;
            }
            for(ExportContractProductPartsEntity parts : partsList){
                //循环终止、取消终止该产品下的所有配件
                //配件修改
                ExportContractProductPartsEntity exportContractProductParts = new ExportContractProductPartsEntity();
                exportContractProductParts.setId(parts.getId());
                exportContractProductParts.setStatus(req.getStatus());
                exportContractProductPartsService.update(exportContractProductParts);
            }

        } else {
            //配件修改
            ExportContractProductPartsEntity exportContractProductParts = new ExportContractProductPartsEntity();
            exportContractProductParts.setId(req.getId());
            exportContractProductParts.setStatus(req.getStatus());
            exportContractProductPartsService.update(exportContractProductParts);
        }
        return;
    }

    /**
     * 根据产品编码规格编码获取规格信息
     * @param productCode 产品编码
     * @param specificationCode 规格编码
     * @return 规格信息
     */
    public ProductInfoRsp getProductInfoByCode(String productCode, String specificationCode) {
        if (StringUtils.isEmpty(productCode)) {
            return new ProductInfoRsp();
        }
        return stockService.getProductInfoByCode(productCode, specificationCode);
    }
}
